From a3a2438086719fc1b1bc92911ae858eb6cb536fb Mon Sep 17 00:00:00 2001 From: Roshan Naik Date: Fri, 23 Jan 2026 22:36:55 +0530 Subject: [PATCH] Added emoji picker and API integration --- package-lock.json | 91 +++++++++++-- package.json | 5 +- src/api/{lib.ts => lib.cs} | 0 src/api/types.ts | 1 + src/ui/features/goalmanager/GoalManager.tsx | 138 +++++++++++++++----- src/ui/pages/Main/goals/GoalCard.tsx | 8 ++ 6 files changed, 197 insertions(+), 46 deletions(-) rename src/api/{lib.ts => lib.cs} (100%) diff --git a/package-lock.json b/package-lock.json index 240aecf..f15b32a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ "@material-ui/core": "^4.12.4", "@material-ui/pickers": "^3.3.10", "@reduxjs/toolkit": "^1.5.1", - "@types/emoji-mart": "^3.0.5", "@types/node": "^17.0.41", "@types/react": "^16.9.0", "@types/react-redux": "^7.1.7", @@ -35,7 +34,7 @@ "web-vitals": "^2.1.4" }, "devDependencies": { - "@types/emoji-mart": "^3.0.9", + "@types/emoji-mart": "^3.0.14", "@types/react-dom": "^18.0.5", "@types/styled-components": "^5.1.25" } @@ -75,6 +74,7 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz", "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", @@ -894,6 +894,7 @@ "version": "7.17.12", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.17.12.tgz", "integrity": "sha512-B8QIgBvkIG6G2jgsOHQUist7Sm0EBLDCx8sen072IwqNuzMegZNXrYnSv77cYzA8mLDZAfQYqsLIhimiP1s2HQ==", + "peer": true, "dependencies": { "@babel/helper-plugin-utils": "^7.17.12" }, @@ -1456,6 +1457,7 @@ "version": "7.17.12", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.12.tgz", "integrity": "sha512-Lcaw8bxd1DKht3thfD4A12dqo1X16he1Lm8rIv8sTwjAYNInRS1qHa9aJoqvzpscItXvftKDCfaEQzwoVyXpEQ==", + "peer": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -3699,10 +3701,11 @@ } }, "node_modules/@types/emoji-mart": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@types/emoji-mart/-/emoji-mart-3.0.9.tgz", - "integrity": "sha512-qdBo/2Y8MXaJ/2spKjDZocuq79GpnOhkwMHnK2GnVFa8WYFgfA+ei6sil3aeWQPCreOKIx9ogPpR5+7MaOqYAA==", + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@types/emoji-mart/-/emoji-mart-3.0.14.tgz", + "integrity": "sha512-/vMkVnet466bK37ugf2jry9ldCZklFPXYMB2m+qNo3vkP2I7L0cvtNFPKAjfcHgPg9Z8pbYqVqZn7AgsC0qf+g==", "dev": true, + "license": "MIT", "dependencies": { "@types/react": "*" } @@ -3856,6 +3859,7 @@ "version": "16.14.26", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.26.tgz", "integrity": "sha512-c/5CYyciOO4XdFcNhZW1O2woVx86k4T+DO2RorHZL7EhitkNQgSD/SgpdZJAUJa/qjVgOmTM44gHkAdZSXeQuQ==", + "peer": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -3998,6 +4002,7 @@ "version": "5.27.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.1.tgz", "integrity": "sha512-6dM5NKT57ZduNnJfpY81Phe9nc9wolnMCnknb1im6brWi1RYv84nbMS3olJa27B6+irUVV1X/Wb+Am0FjJdGFw==", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.27.1", "@typescript-eslint/type-utils": "5.27.1", @@ -4048,6 +4053,7 @@ "version": "5.27.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.1.tgz", "integrity": "sha512-7Va2ZOkHi5NP+AZwb5ReLgNF6nWLGTeUJfxdkVUAPPSaAdbWNnFZzLZ4EGGmmiCTg+AwlbE1KyUYTBglosSLHQ==", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "5.27.1", "@typescript-eslint/types": "5.27.1", @@ -4370,6 +4376,7 @@ "version": "8.7.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4477,6 +4484,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5241,6 +5249,7 @@ "url": "https://tidelift.com/funding/github/npm/browserslist" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001349", "electron-to-chromium": "^1.4.147", @@ -5914,6 +5923,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -6228,6 +6238,7 @@ "version": "2.28.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", + "peer": true, "engines": { "node": ">=0.11" }, @@ -6611,6 +6622,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-3.0.1.tgz", "integrity": "sha512-sxpmMKxqLvcscu6mFn9ITHeZNkGzIvD0BSNFE/LJESPbCA8s1jM6bCDPjWbV31xHq7JXaxgpHxLB54RCbBZSlg==", + "license": "BSD-3-Clause", "dependencies": { "@babel/runtime": "^7.0.0", "prop-types": "^15.6.0" @@ -6848,6 +6860,7 @@ "version": "8.17.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.17.0.tgz", "integrity": "sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==", + "peer": true, "dependencies": { "@eslint/eslintrc": "^1.3.0", "@humanwhocodes/config-array": "^0.9.2", @@ -9264,6 +9277,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "peer": true, "dependencies": { "@jest/core": "^27.5.1", "import-local": "^3.0.2", @@ -11692,6 +11706,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -12428,6 +12443,7 @@ "url": "https://tidelift.com/funding/github/npm/postcss" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -13454,6 +13470,7 @@ "version": "6.0.10", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -13649,6 +13666,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -13807,6 +13825,7 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -13952,6 +13971,7 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -13975,6 +13995,7 @@ "version": "7.2.8", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz", "integrity": "sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==", + "peer": true, "dependencies": { "@babel/runtime": "^7.15.4", "@types/react-redux": "^7.1.20", @@ -14004,6 +14025,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -14153,6 +14175,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", + "peer": true, "dependencies": { "@babel/runtime": "^7.9.2" } @@ -14457,6 +14480,7 @@ "version": "2.75.6", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.6.tgz", "integrity": "sha512-OEf0TgpC9vU6WGROJIk1JA3LR5vk/yvqlzxqdrE2CzzXnqKXNzbAwlWUXis8RS3ZPe7LAq+YUxsRa0l3r27MLA==", + "peer": true, "bin": { "rollup": "dist/bin/rollup" }, @@ -14562,6 +14586,7 @@ "version": "1.52.3", "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.3.tgz", "integrity": "sha512-LNNPJ9lafx+j1ArtA7GyEJm9eawXN8KlA1+5dF6IZyoONg1Tyo/g+muOsENWJH/2Q1FHbbV4UwliU0cXMa/VIA==", + "peer": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -15209,6 +15234,7 @@ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.5.tgz", "integrity": "sha512-ndETJ9RKaaL6q41B69WudeqLzOpY1A/ET/glXkNZ2T7dPjPqpPCXXQjDFYZWwNnE5co0wX+gTCqx9mfxTmSIPg==", "hasInstallScript": true, + "peer": true, "dependencies": { "@babel/helper-module-imports": "^7.0.0", "@babel/traverse": "^7.4.5", @@ -15729,6 +15755,7 @@ "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "peer": true, "engines": { "node": ">=10" }, @@ -15760,6 +15787,7 @@ "version": "4.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -15997,6 +16025,7 @@ "version": "5.73.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz", "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -16065,6 +16094,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -16114,6 +16144,7 @@ "version": "4.9.2", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.2.tgz", "integrity": "sha512-H95Ns95dP24ZsEzO6G9iT+PNw4Q7ltll1GfJHV4fKphuHWgKFzGHWi4alTlTnpk1SPPk41X+l2RB7rLfIhnB9Q==", + "peer": true, "dependencies": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -16164,6 +16195,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -16476,6 +16508,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -16871,6 +16904,7 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz", "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==", + "peer": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", @@ -17434,6 +17468,7 @@ "version": "7.17.12", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.17.12.tgz", "integrity": "sha512-B8QIgBvkIG6G2jgsOHQUist7Sm0EBLDCx8sen072IwqNuzMegZNXrYnSv77cYzA8mLDZAfQYqsLIhimiP1s2HQ==", + "peer": true, "requires": { "@babel/helper-plugin-utils": "^7.17.12" } @@ -17780,6 +17815,7 @@ "version": "7.17.12", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.12.tgz", "integrity": "sha512-Lcaw8bxd1DKht3thfD4A12dqo1X16he1Lm8rIv8sTwjAYNInRS1qHa9aJoqvzpscItXvftKDCfaEQzwoVyXpEQ==", + "peer": true, "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -19308,9 +19344,9 @@ } }, "@types/emoji-mart": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@types/emoji-mart/-/emoji-mart-3.0.9.tgz", - "integrity": "sha512-qdBo/2Y8MXaJ/2spKjDZocuq79GpnOhkwMHnK2GnVFa8WYFgfA+ei6sil3aeWQPCreOKIx9ogPpR5+7MaOqYAA==", + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@types/emoji-mart/-/emoji-mart-3.0.14.tgz", + "integrity": "sha512-/vMkVnet466bK37ugf2jry9ldCZklFPXYMB2m+qNo3vkP2I7L0cvtNFPKAjfcHgPg9Z8pbYqVqZn7AgsC0qf+g==", "dev": true, "requires": { "@types/react": "*" @@ -19465,6 +19501,7 @@ "version": "16.14.26", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.26.tgz", "integrity": "sha512-c/5CYyciOO4XdFcNhZW1O2woVx86k4T+DO2RorHZL7EhitkNQgSD/SgpdZJAUJa/qjVgOmTM44gHkAdZSXeQuQ==", + "peer": true, "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -19611,6 +19648,7 @@ "version": "5.27.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.1.tgz", "integrity": "sha512-6dM5NKT57ZduNnJfpY81Phe9nc9wolnMCnknb1im6brWi1RYv84nbMS3olJa27B6+irUVV1X/Wb+Am0FjJdGFw==", + "peer": true, "requires": { "@typescript-eslint/scope-manager": "5.27.1", "@typescript-eslint/type-utils": "5.27.1", @@ -19635,6 +19673,7 @@ "version": "5.27.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.1.tgz", "integrity": "sha512-7Va2ZOkHi5NP+AZwb5ReLgNF6nWLGTeUJfxdkVUAPPSaAdbWNnFZzLZ4EGGmmiCTg+AwlbE1KyUYTBglosSLHQ==", + "peer": true, "requires": { "@typescript-eslint/scope-manager": "5.27.1", "@typescript-eslint/types": "5.27.1", @@ -19876,7 +19915,8 @@ "acorn": { "version": "8.7.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", - "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "peer": true }, "acorn-globals": { "version": "6.0.0", @@ -19954,6 +19994,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -20525,6 +20566,7 @@ "version": "4.20.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.4.tgz", "integrity": "sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==", + "peer": true, "requires": { "caniuse-lite": "^1.0.30001349", "electron-to-chromium": "^1.4.147", @@ -20996,6 +21038,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -21231,7 +21274,8 @@ "date-fns": { "version": "2.28.0", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", - "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==" + "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", + "peer": true }, "debug": { "version": "4.3.4", @@ -21696,6 +21740,7 @@ "version": "8.17.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.17.0.tgz", "integrity": "sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==", + "peer": true, "requires": { "@eslint/eslintrc": "^1.3.0", "@humanwhocodes/config-array": "^0.9.2", @@ -23419,6 +23464,7 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "peer": true, "requires": { "@jest/core": "^27.5.1", "import-local": "^3.0.2", @@ -25221,6 +25267,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -25744,6 +25791,7 @@ "version": "8.4.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "peer": true, "requires": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -26322,6 +26370,7 @@ "version": "6.0.10", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "peer": true, "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -26461,6 +26510,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "peer": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -26574,6 +26624,7 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "peer": true, "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -26682,6 +26733,7 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "peer": true, "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -26702,6 +26754,7 @@ "version": "7.2.8", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz", "integrity": "sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==", + "peer": true, "requires": { "@babel/runtime": "^7.15.4", "@types/react-redux": "^7.1.20", @@ -26721,7 +26774,8 @@ "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", - "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" + "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", + "peer": true }, "react-scripts": { "version": "5.0.1", @@ -26837,6 +26891,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", + "peer": true, "requires": { "@babel/runtime": "^7.9.2" } @@ -27054,6 +27109,7 @@ "version": "2.75.6", "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.6.tgz", "integrity": "sha512-OEf0TgpC9vU6WGROJIk1JA3LR5vk/yvqlzxqdrE2CzzXnqKXNzbAwlWUXis8RS3ZPe7LAq+YUxsRa0l3r27MLA==", + "peer": true, "requires": { "fsevents": "~2.3.2" } @@ -27129,6 +27185,7 @@ "version": "1.52.3", "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.3.tgz", "integrity": "sha512-LNNPJ9lafx+j1ArtA7GyEJm9eawXN8KlA1+5dF6IZyoONg1Tyo/g+muOsENWJH/2Q1FHbbV4UwliU0cXMa/VIA==", + "peer": true, "requires": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -27616,6 +27673,7 @@ "version": "5.3.5", "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.5.tgz", "integrity": "sha512-ndETJ9RKaaL6q41B69WudeqLzOpY1A/ET/glXkNZ2T7dPjPqpPCXXQjDFYZWwNnE5co0wX+gTCqx9mfxTmSIPg==", + "peer": true, "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/traverse": "^7.4.5", @@ -28004,7 +28062,8 @@ "type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "peer": true }, "type-is": { "version": "1.6.18", @@ -28026,7 +28085,8 @@ "typescript": { "version": "4.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.3.tgz", - "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==" + "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", + "peer": true }, "unbox-primitive": { "version": "1.0.2", @@ -28205,6 +28265,7 @@ "version": "5.73.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz", "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==", + "peer": true, "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -28264,6 +28325,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -28301,6 +28363,7 @@ "version": "4.9.2", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.9.2.tgz", "integrity": "sha512-H95Ns95dP24ZsEzO6G9iT+PNw4Q7ltll1GfJHV4fKphuHWgKFzGHWi4alTlTnpk1SPPk41X+l2RB7rLfIhnB9Q==", + "peer": true, "requires": { "@types/bonjour": "^3.5.9", "@types/connect-history-api-fallback": "^1.3.5", @@ -28337,6 +28400,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -28559,6 +28623,7 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", diff --git a/package.json b/package.json index 87958ce..9291828 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "@material-ui/core": "^4.12.4", "@material-ui/pickers": "^3.3.10", "@reduxjs/toolkit": "^1.5.1", - "@types/emoji-mart": "^3.0.5", "@types/node": "^17.0.41", "@types/react": "^16.9.0", "@types/react-redux": "^7.1.7", @@ -55,8 +54,8 @@ ] }, "devDependencies": { - "@types/emoji-mart": "^3.0.9", + "@types/emoji-mart": "^3.0.14", "@types/react-dom": "^18.0.5", "@types/styled-components": "^5.1.25" } -} \ No newline at end of file +} diff --git a/src/api/lib.ts b/src/api/lib.cs similarity index 100% rename from src/api/lib.ts rename to src/api/lib.cs diff --git a/src/api/types.ts b/src/api/types.ts index f75edad..6193f2a 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -27,6 +27,7 @@ export interface Goal { accountId: string transactionIds: string[] tagIds: string[] + icon?: string } export interface Tag { diff --git a/src/ui/features/goalmanager/GoalManager.tsx b/src/ui/features/goalmanager/GoalManager.tsx index 0779dda..043b6a1 100644 --- a/src/ui/features/goalmanager/GoalManager.tsx +++ b/src/ui/features/goalmanager/GoalManager.tsx @@ -3,6 +3,8 @@ import { faDollarSign, IconDefinition } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { MaterialUiPickersDate } from '@material-ui/pickers/typings/date' import 'date-fns' +import { Picker } from 'emoji-mart' +import 'emoji-mart/css/emoji-mart.css' import React, { useEffect, useState } from 'react' import styled from 'styled-components' import { updateGoal as updateGoalApi } from '../../../api/lib' @@ -13,71 +15,121 @@ import DatePicker from '../../components/DatePicker' import { Theme } from '../../components/Theme' type Props = { goal: Goal } + export function GoalManager(props: Props) { const dispatch = useAppDispatch() + // We fetch the "Live" goal from Redux. This updates instantly when changed. const goal = useAppSelector(selectGoalsMap)[props.goal.id] const [name, setName] = useState(null) const [targetDate, setTargetDate] = useState(null) const [targetAmount, setTargetAmount] = useState(null) + + const [showPicker, setShowPicker] = useState(false) useEffect(() => { - setName(props.goal.name) - setTargetDate(props.goal.targetDate) - setTargetAmount(props.goal.targetAmount) - }, [ - props.goal.id, - props.goal.name, - props.goal.targetDate, - props.goal.targetAmount, - ]) - - useEffect(() => { - setName(goal.name) - }, [goal.name]) + // Initialize state from the live goal + if (goal) { + setName(goal.name) + setTargetDate(goal.targetDate) + setTargetAmount(goal.targetAmount) + } + }, [goal]) const updateNameOnChange = (event: React.ChangeEvent) => { const nextName = event.target.value setName(nextName) const updatedGoal: Goal = { - ...props.goal, + ...goal, name: nextName, } dispatch(updateGoalRedux(updatedGoal)) - updateGoalApi(props.goal.id, updatedGoal) + updateGoalApi(goal.id, updatedGoal) } const updateTargetAmountOnChange = (event: React.ChangeEvent) => { const nextTargetAmount = parseFloat(event.target.value) setTargetAmount(nextTargetAmount) const updatedGoal: Goal = { - ...props.goal, - name: name ?? props.goal.name, - targetDate: targetDate ?? props.goal.targetDate, + ...goal, + name: name ?? goal.name, + targetDate: targetDate ?? goal.targetDate, targetAmount: nextTargetAmount, } dispatch(updateGoalRedux(updatedGoal)) - updateGoalApi(props.goal.id, updatedGoal) + updateGoalApi(goal.id, updatedGoal) } const pickDateOnChange = (date: MaterialUiPickersDate) => { if (date != null) { setTargetDate(date) const updatedGoal: Goal = { - ...props.goal, - name: name ?? props.goal.name, - targetDate: date ?? props.goal.targetDate, - targetAmount: targetAmount ?? props.goal.targetAmount, + ...goal, + name: name ?? goal.name, + targetDate: date ?? goal.targetDate, + targetAmount: targetAmount ?? goal.targetAmount, } dispatch(updateGoalRedux(updatedGoal)) - updateGoalApi(props.goal.id, updatedGoal) + updateGoalApi(goal.id, updatedGoal) + } + } + + // --- THE EMOJI HANDLER --- + const updateIconOnSelect = (emoji: any) => { + console.log("Emoji Selected:", emoji); // Check your console if this prints! + + setShowPicker(false) + + const updatedGoal: Goal = { + ...goal, // Grab the latest goal state + icon: emoji.native, // Set the new icon } + + // 1. Update the screen immediately (Redux) + dispatch(updateGoalRedux(updatedGoal)) + + // 2. Save to the database + updateGoalApi(goal.id, updatedGoal) } + const togglePicker = (e: React.MouseEvent) => { + e.stopPropagation(); + setShowPicker(!showPicker); + } + + if (!goal) return null; // Safety check + return ( - + + {/* Header Area */} +
+
+ + {/* USE 'goal.icon' HERE (The live one), NOT 'props.goal.icon' */} + {goal.icon ? ( + {goal.icon} + ) : ( + + + )} + + {/* Picker Popup */} + {showPicker && ( +
+ +
+ )} +
+ + +
@@ -96,14 +148,14 @@ export function GoalManager(props: Props) { - {props.goal.balance} + {goal.balance} - {new Date(props.goal.created).toLocaleDateString()} + {new Date(goal.created).toLocaleDateString()}
@@ -111,9 +163,6 @@ export function GoalManager(props: Props) { } type FieldProps = { name: string; icon: IconDefinition } -type AddIconButtonContainerProps = { shouldShow: boolean } -type GoalIconContainerProps = { shouldShow: boolean } -type EmojiPickerContainerProps = { isOpen: boolean; hasIcon: boolean } const Field = (props: FieldProps) => ( @@ -122,6 +171,7 @@ const Field = (props: FieldProps) => ( ) +// STYLES const GoalManagerContainer = styled.div` display: flex; flex-direction: column; @@ -147,6 +197,7 @@ const NameInput = styled.input` font-size: 4rem; font-weight: bold; color: ${({ theme }: { theme: Theme }) => theme.text}; + width: 100%; ` const FieldName = styled.h1` @@ -182,3 +233,30 @@ const StringInput = styled.input` const Value = styled.div` margin-left: 2rem; ` + +const GoalIcon = styled.div` + font-size: 3rem; + cursor: pointer; + user-select: none; + transition: transform 0.1s; + &:hover { + transform: scale(1.1); + } +` + +const AddIconButton = styled.div` + width: 3rem; + height: 3rem; + border-radius: 50%; + border: 2px dashed rgba(174, 174, 174, 1); + display: flex; + justify-content: center; + align-items: center; + color: rgba(174, 174, 174, 1); + font-size: 2rem; + cursor: pointer; + &:hover { + border-color: white; + color: white; + } +` \ No newline at end of file diff --git a/src/ui/pages/Main/goals/GoalCard.tsx b/src/ui/pages/Main/goals/GoalCard.tsx index e8f6d0a..c70167c 100644 --- a/src/ui/pages/Main/goals/GoalCard.tsx +++ b/src/ui/pages/Main/goals/GoalCard.tsx @@ -29,6 +29,8 @@ export default function GoalCard(props: Props) { ${goal.targetAmount} {asLocaleDateString(goal.targetDate)} + {/* This checks if an icon exists, and if so, displays it */} + {goal.icon && {goal.icon}} ) } @@ -54,3 +56,9 @@ const TargetDate = styled.h4` color: rgba(174, 174, 174, 1); font-size: 1rem; ` + +// New style for the emoji +const GoalIcon = styled.div` + font-size: 4rem; + margin-top: 0.5rem; +` \ No newline at end of file