From 60ddf0520e2bcb165c16da56c6ee313bc57e2ecb Mon Sep 17 00:00:00 2001 From: james fitzsimons Date: Tue, 25 Nov 2025 22:09:02 +0000 Subject: [PATCH] Slight style changes. might revert. fixed scroll. --- .../app/__pycache__/__init__.cpython-314.pyc | Bin 165 -> 157 bytes .../app/__pycache__/database.cpython-314.pyc | Bin 923 -> 915 bytes backend/app/__pycache__/main.cpython-314.pyc | Bin 1252 -> 1244 bytes .../app/__pycache__/models.cpython-314.pyc | Bin 5728 -> 5720 bytes .../__pycache__/folders.cpython-314.pyc | Bin 4657 -> 4649 bytes .../routes/__pycache__/notes.cpython-314.pyc | Bin 4173 -> 4165 bytes backend/notes.db | Bin 12288 -> 20480 bytes frontend/package-lock.json | 518 +++++++++++++++++- frontend/package.json | 3 +- frontend/src/api/notes.tsx | 19 +- .../assets/fontawesome/svg/circle-check.svg | 1 + .../src/assets/fontawesome/svg/rotate.svg | 1 + frontend/src/main.css | 2 + frontend/src/pages/Home.tsx | 281 ++++++---- frontend/vite.config.mts | 5 +- 15 files changed, 721 insertions(+), 109 deletions(-) create mode 100644 frontend/src/assets/fontawesome/svg/circle-check.svg create mode 100644 frontend/src/assets/fontawesome/svg/rotate.svg diff --git a/backend/app/__pycache__/__init__.cpython-314.pyc b/backend/app/__pycache__/__init__.cpython-314.pyc index 5d59c995b3b43c88d330988e417c235ecdbc86ff..e78c6d7f60c7048c5fa58cf10def2be49355ca7f 100644 GIT binary patch delta 48 zcmZ3=IG2%In~#@^0SNN-xlmQ?Axq?V=Tt`kArWU7VmQ)pI=H}-W>${|urRL-p Kq!vw#bO8X2{t+Ai diff --git a/backend/app/__pycache__/database.cpython-314.pyc b/backend/app/__pycache__/database.cpython-314.pyc index ddda32dc68b68ab8ef2c8abcdb58eea40dfb245d..c394bc680e07e0f47db9993fd1baa32e9189e063 100644 GIT binary patch delta 51 zcmbQuKAD|cn~#@^0SKmSR@lg$$|z~2pOK%Ns-KmZn^{t&?~+=Unv-9Uo0?a$c_Jeh F6987C4-EhS delta 59 zcmbQtKAW9en~#@^0SMS#l{a#yGAcUhhZd(673*gu=B5^>WtLPGXXfVT73;gCmZj$8 N7o-+#?quX*0sy`#5r6;y diff --git a/backend/app/__pycache__/main.cpython-314.pyc b/backend/app/__pycache__/main.cpython-314.pyc index a0a2cf33df64c76c2c11baa3334bd1ad2dfca64f..1c5498b086091b65441ffd4b9d575c7d6ab8149f 100644 GIT binary patch delta 51 zcmaFDd54o*n~#@^0SJsvDs1GgWRf(~&&bbB)z3=I%`B@$_53&FN delta 59 zcmcb^`Gk{On~#@^0SMS#l{a!%GAY{WhZd(673*gu=B5^>WtLPGXXfVT73;gCmZj$8 N7o-+#p37v<1OVfr5^(?k diff --git a/backend/app/__pycache__/models.cpython-314.pyc b/backend/app/__pycache__/models.cpython-314.pyc index 25f616e6405d158c9b8074626dc42153d4f4a92a..001efb13a71da49f4ec3560c4f61db24f34c2284 100644 GIT binary patch delta 51 zcmaE$b3=z)n~#@^0SMIBDsJTVW0ADb&&bbB)z3=I%`BWtLPGXXfVT73;gCmZj$8 N7o-+#E@F8m2mtHY6BPge diff --git a/backend/app/routes/__pycache__/folders.cpython-314.pyc b/backend/app/routes/__pycache__/folders.cpython-314.pyc index e1088134c7d2e09520dadeef11e914d992d7b119..892c1223fb9e8fbf8df42aa06e1fd7891c26f075 100644 GIT binary patch delta 51 zcmdm}vQmXxn~#@^0SNThDsJSKV3u^y&&bbB)z3=I%`BWtLPGXXfVT73;gCmZj$8 N7o-+#wqbtD2LQ^B5=8(2 diff --git a/backend/app/routes/__pycache__/notes.cpython-314.pyc b/backend/app/routes/__pycache__/notes.cpython-314.pyc index 4c1f6ad407a975fa2268a174000c3eeb24ad7fcd..adec199e0eb926bb4296cfd20a4213ba48106e82 100644 GIT binary patch delta 51 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 delta 497 zcmXBO%W|4v0ES^~CT(4)wc9L`Nv11v;OFoI&NvwaiVBF}30wsu2v+a_N^qmzK{M_< zU9??xrqkPKufTig6=YE}S%2?0^K8DRHg}&-j?)N&96g@hrqaLezU5x0a(g7V|DAvL zJ@>e|-0e?4WHZl2<_XCu*)N%=!}Kq+-ku)4LHq^6vIe)B)}z+kD)(yU!z7vv9FNjR zI1~#M@W(S;>SF?Hs}ANvUn`XgL|5A5|p6WFyNP?HrsWkI-Eoi90{__G?HPdl(c!DybtS~uU2edn3IOW zSg;zJwi70LhwtgG8O&T@H-jY(_^2lC{@h;VUsP0)Ag^fxBO&+? Da37W| diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 260d801..65a6628 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -25,7 +25,8 @@ "@types/react": "^19.2.6", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^4.7.0", - "vite": "^5.4.21" + "vite": "^5.4.21", + "vite-plugin-svgr": "^4.5.0" } }, "node_modules/@babel/code-frame": { @@ -59,6 +60,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -635,6 +637,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.3.tgz", "integrity": "sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", @@ -724,6 +727,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", "license": "MIT", + "peer": true, "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } @@ -733,6 +737,7 @@ "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.38.8.tgz", "integrity": "sha512-XcE9fcnkHCbWkjeKyi0lllwXmBLtyYb5dt89dJyx23I9+LSh5vZDIuk7OLG4VM1lgrXZQcY6cxyZyk5WVPRv/A==", "license": "MIT", + "peer": true, "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", @@ -1269,6 +1274,7 @@ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-7.1.0.tgz", "integrity": "sha512-fNxRUk1KhjSbnbuBxlWSnBLKLBNun52ZBTcs22H/xEEzM6Ap81ZFTQ4bZBxVQGQgVY0xugKGoRcCbaKjLQ3XZA==", "license": "MIT", + "peer": true, "dependencies": { "@fortawesome/fontawesome-common-types": "7.1.0" }, @@ -1633,6 +1639,7 @@ "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", "license": "MIT", + "peer": true, "dependencies": { "@lezer/common": "^1.3.0" } @@ -2670,6 +2677,29 @@ "dev": true, "license": "MIT" }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.53.3", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", @@ -2962,6 +2992,232 @@ "integrity": "sha512-Gfkvwk9o9kE9r9XNBmJRfV8zONvXThnm1tcuojL04Uy5uRyqg93DC83lDebl0rocZCfKSjUv+fWYtMQmEDJldg==", "license": "MIT" }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, "node_modules/@tailwindcss/node": { "version": "4.1.17", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.17.tgz", @@ -3330,6 +3586,7 @@ "integrity": "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -3340,6 +3597,7 @@ "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "devOptional": true, "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -3376,6 +3634,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3483,6 +3742,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", @@ -3534,6 +3794,29 @@ "node": ">= 0.4" } }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001756", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", @@ -3678,6 +3961,33 @@ "node": ">=18" } }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/crelt": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", @@ -3801,6 +4111,17 @@ "node": ">=0.3.1" } }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/dotenv": { "version": "16.6.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", @@ -3863,6 +4184,29 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -4053,6 +4397,13 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, "node_modules/event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", @@ -4285,6 +4636,23 @@ ], "license": "BSD-3-Clause" }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/intersection-observer": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.10.0.tgz", @@ -4316,6 +4684,13 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, "node_modules/is-decimal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", @@ -4341,7 +4716,6 @@ "resolved": "https://registry.npmjs.org/isomorphic.js/-/isomorphic.js-0.2.5.tgz", "integrity": "sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==", "license": "MIT", - "peer": true, "funding": { "type": "GitHub Sponsors ❤", "url": "https://github.com/sponsors/dmonad" @@ -4387,6 +4761,13 @@ "node": ">=6" } }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -4420,7 +4801,6 @@ "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.114.tgz", "integrity": "sha512-gcxmNFzA4hv8UYi8j43uPlQ7CGcyMJ2KQb5kZASw6SnAKAf10hK12i2fjrS3Cl/ugZa5Ui6WwIu1/6MIXiHttQ==", "license": "MIT", - "peer": true, "dependencies": { "isomorphic.js": "^0.2.4" }, @@ -4686,6 +5066,13 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -4708,6 +5095,16 @@ "loose-envify": "cli.js" } }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -5757,6 +6154,17 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "license": "ISC" }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/node-releases": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", @@ -5779,6 +6187,19 @@ "integrity": "sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==", "license": "MIT" }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/parse-entities": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", @@ -5804,12 +6225,54 @@ "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", "license": "MIT" }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -5888,6 +6351,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -5909,6 +6373,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -6072,6 +6537,16 @@ } } }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/rollup": { "version": "4.53.3", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", @@ -6150,6 +6625,17 @@ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "license": "MIT" }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -6197,6 +6683,13 @@ "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", "license": "MIT" }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true, + "license": "MIT" + }, "node_modules/tabbable": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.3.0.tgz", @@ -6207,7 +6700,8 @@ "version": "4.1.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.17.tgz", "integrity": "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/tapable": { "version": "2.3.0", @@ -6428,6 +6922,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -6482,6 +6977,21 @@ } } }, + "node_modules/vite-plugin-svgr": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.5.0.tgz", + "integrity": "sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.2.0", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" + }, + "peerDependencies": { + "vite": ">=2.6.0" + } + }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", diff --git a/frontend/package.json b/frontend/package.json index 91e5392..3f252ba 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,6 +25,7 @@ "@types/react": "^19.2.6", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^4.7.0", - "vite": "^5.4.21" + "vite": "^5.4.21", + "vite-plugin-svgr": "^4.5.0" } } diff --git a/frontend/src/api/notes.tsx b/frontend/src/api/notes.tsx index 8e69c89..733864e 100644 --- a/frontend/src/api/notes.tsx +++ b/frontend/src/api/notes.tsx @@ -51,11 +51,26 @@ const fetchNotes = async () => { return decryptedNotes; }; +const updateNote = async (id: number, note: Partial) => { + var key = await deriveKey("Test"); + var encryptedNote: Partial = {}; + if (note.content) { + encryptedNote.content = await encryptString(note.content, key); + } + if (note.title) { + encryptedNote.title = await encryptString(note.title, key); + } + if (note.folder_id) { + encryptedNote.folder_id = note.folder_id; + } + + return axios.patch(`${API_URL}/notes/${id}`, encryptedNote); +}; + export const notesApi = { list: () => fetchNotes(), get: (id: number) => axios.get(`${API_URL}/notes/${id}`), create: (note: NoteCreate) => createNote(note), - update: (id: number, note: Partial) => - axios.patch(`${API_URL}/notes/${id}`, note), + update: (id: number, note: Partial) => updateNote(id, note), delete: (id: number) => axios.delete(`${API_URL}/notes/${id}`), }; diff --git a/frontend/src/assets/fontawesome/svg/circle-check.svg b/frontend/src/assets/fontawesome/svg/circle-check.svg new file mode 100644 index 0000000..f43d184 --- /dev/null +++ b/frontend/src/assets/fontawesome/svg/circle-check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/assets/fontawesome/svg/rotate.svg b/frontend/src/assets/fontawesome/svg/rotate.svg new file mode 100644 index 0000000..c118432 --- /dev/null +++ b/frontend/src/assets/fontawesome/svg/rotate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/main.css b/frontend/src/main.css index de78009..c296b02 100644 --- a/frontend/src/main.css +++ b/frontend/src/main.css @@ -37,3 +37,5 @@ ol li::marker { .mdxeditor-popup-container > * { background-color: var(--ctp-base) !important; } + + diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx index f01076b..8e56346 100644 --- a/frontend/src/pages/Home.tsx +++ b/frontend/src/pages/Home.tsx @@ -1,7 +1,9 @@ import { codeBlockPlugin, codeMirrorPlugin, + diffSourcePlugin, headingsPlugin, + imagePlugin, linkPlugin, listsPlugin, markdownShortcutPlugin, @@ -9,6 +11,7 @@ import { quotePlugin, SandpackConfig, sandpackPlugin, + tablePlugin, thematicBreakPlugin, } from "@mdxeditor/editor"; import { useEffect, useRef, useState } from "react"; @@ -32,6 +35,8 @@ import { import "@mdxeditor/editor/style.css"; import { DroppableFolder } from "../components/sidebar/DroppableFolder"; import { DraggableNote } from "../components/sidebar/DraggableNote"; +import CheckIcon from "../assets/fontawesome/svg/circle-check.svg?react"; +import SpinnerIcon from "../assets/fontawesome/svg/rotate.svg?react"; const simpleSandpackConfig: SandpackConfig = { defaultPreset: "react", @@ -52,21 +57,43 @@ function Home() { const [folderTree, setFolderTree] = useState(null); const [selectedNote, setSelectedNote] = useState(null); const [title, setTitle] = useState(""); - const [content, setContent] = useState("#"); + const [content, setContent] = useState(""); const [newFolder, setNewFolder] = useState(false); const [newFolderText, setNewFolderText] = useState(""); const [selectedFolder, setSelectedFolder] = useState(null); const [encrypted, setEncrypted] = useState(false); + const [updating, setUpdating] = useState(false); + const pointer = useSensor(PointerSensor, { activationConstraint: { distance: 30, }, }); const sensors = useSensors(pointer); + + const newFolderRef = useRef(null); + useEffect(() => { loadFolderTree(); }, []); + useEffect(() => { + if (newFolder && newFolderRef.current) { + newFolderRef.current.focus(); + } + }, [newFolder]); + + useEffect(() => { + if (!selectedNote) return; + + const timer = setTimeout(async () => { + setUpdating(true); + handleUpdate(); + }, 2000); + + return () => clearTimeout(timer); + }, [content, title]); + const loadFolderTree = async () => { const data = await folderApi.tree(); setFolderTree(data); @@ -82,7 +109,7 @@ function Home() { }; await notesApi.create(newNote); setTitle(""); - setContent("#"); + setContent(""); loadFolderTree(); }; @@ -101,52 +128,46 @@ function Home() { const handleUpdate = async () => { if (!selectedNote) return; await notesApi.update(selectedNote.id, { title, content }); - setSelectedNote(null); - setTitle(""); - setContent("#"); loadFolderTree(); + setTimeout(() => { + setUpdating(false); + }, 1000); }; const handleDelete = async (id: number) => { await notesApi.delete(id); loadFolderTree(); + clearSelection(); }; const selectNote = (note: NoteRead) => { - console.log(note); setSelectedNote(note); setTitle(note.title); - setContent(note.content); + + let cleanContent = note.content.replace(/\\([_\-\[\]\(\)])/g, "$1"); + cleanContent = cleanContent.replace(/^```\s*$/gm, ""); + setContent(cleanContent); }; const clearSelection = () => { setSelectedNote(null); setTitle(""); - setContent("#"); + setContent(""); }; - const newFolderRef = useRef(null); - - useEffect(() => { - if (newFolder && newFolderRef.current) { - newFolderRef.current.focus(); - } - }, [newFolder]); - const renderFolder = (folder: FolderTreeNode, depth: number = 0) => (
0 ? "1rem" : "0" }} className="flex flex-col" + style={{ marginLeft: depth > 0 ? "1.5rem" : "0" }} > -
+
{folder.notes.map((note) => ( -
+
+ {/* Sidebar */}
e.preventDefault()} onTouchMove={(e) => e.preventDefault()} > -

Notes

- -
- - + {/* Header */} +
+

FastNotes

+
+ + +
+ {/* New folder input */} {newFolder && ( -
+
setNewFolder(false)} onChange={(e) => setNewFolderText(e.target.value)} value={newFolderText} type="text" - placeholder="new folder" - className="border-ctp-mauve border rounded-md px-2 w-full focus:outline-none focus:ring-1 focus:ring-ctp-mauve focus:border-ctp-mauve bg-ctp-base" + placeholder="Folder name..." + className="border border-ctp-mauve rounded-md px-3 py-2 w-full focus:outline-none focus:ring-2 focus:ring-ctp-mauve bg-ctp-base text-ctp-text placeholder:text-ctp-overlay0" ref={newFolderRef} onKeyDown={(e) => { if (e.key === "Enter") { handleCreateFolder(); } + if (e.key === "Escape") { + setNewFolder(false); + } }} />
)} - {/* Render folder tree */} - {folderTree?.folders.map((folder) => renderFolder(folder))} + {/* Folder tree */} +
+ {folderTree?.folders.map((folder) => renderFolder(folder))} +
- {/* Render orphaned notes */} + {/* Orphaned notes */} {folderTree?.orphaned_notes && folderTree.orphaned_notes.length > 0 && ( -
-
Unsorted
+
+ {/*
+ Unsorted +
*/} {folderTree.orphaned_notes.map((note) => ( -
-
- setTitle(e.target.value)} - style={{ - padding: "0.5rem", - marginBottom: "1rem", - fontSize: "1.5rem", - border: "1px solid #ccc", - }} - /> - -
+ {/* Main editor area */} +
+ {/* Top accent bar */} +
+ + {/* Content area with padding */} +
+ {/* Title input */} + setTitle(e.target.value)} + className="w-full px-0 py-3 mb-4 text-3xl font-semibold bg-transparent border-b border-ctp-surface2 focus:outline-none focus:border-ctp-mauve transition-colors placeholder:text-ctp-overlay0 text-ctp-text" + /> + + {/* Editor */} +
+ +
+
+ + {/* Action bar */} +
{selectedNote ? ( <> - + - + ) : ( - + )} - setEncrypted(!encrypted)} - /> + + {/* Encryption toggle */} + {/**/}
+ + {/* Status indicator */} +
+ {updating ? ( + <> + + + Saving... + + + ) : ( + <> + + + Saved + + + )} +
); diff --git a/frontend/vite.config.mts b/frontend/vite.config.mts index a76d6f7..ff1e9be 100644 --- a/frontend/vite.config.mts +++ b/frontend/vite.config.mts @@ -1,9 +1,10 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; -import tailwindcss from "@tailwindcss/vite" +import tailwindcss from "@tailwindcss/vite"; +import svgr from "vite-plugin-svgr"; export default defineConfig({ - plugins: [tailwindcss(), react()], + plugins: [tailwindcss(), react(), svgr()], server: { port: 5173, proxy: {