diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..7674d89 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": true, + "singleQuote": true +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a209608..81387c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "vote", + "name": "chat", "version": "0.1.0", "lockfileVersion": 1, "requires": true, @@ -3865,11 +3865,6 @@ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==" }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" - }, "check-types": { "version": "11.1.2", "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.1.2.tgz", @@ -3972,19 +3967,6 @@ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" - }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -5199,23 +5181,23 @@ "integrity": "sha512-ol/0WzjL4NS4Kqy9VD6xXQON91xIihDT36sYCew/G/bnd1v0/4D+kahp26JauQhgFUjrdva3kRSo7URcUmQ+qw==" }, "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" }, "dependencies": { "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==" + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" } } }, @@ -6230,16 +6212,6 @@ } } }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -6366,14 +6338,6 @@ "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, "file-entry-cache": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", @@ -7057,6 +7021,19 @@ "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -7439,9 +7416,9 @@ "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" }, "immer": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/immer/-/immer-7.0.9.tgz", - "integrity": "sha512-Vs/gxoM4DqNAYR7pugIxi0Xc8XAun/uy7AQu4fLLqaTBHxjOP9pJ266Q9MWA/ly4z6rAFZbvViOtihxUZ7O28A==" + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz", + "integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==" }, "import-cwd": { "version": "2.1.0", @@ -7529,94 +7506,9 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" - }, - "inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } - } + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, "internal-ip": { "version": "4.3.0", @@ -10008,6 +9900,15 @@ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" }, + "mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "requires": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + } + }, "mini-css-extract-plugin": { "version": "0.11.3", "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.3.tgz", @@ -10205,11 +10106,6 @@ "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=" }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, "nanoid": { "version": "3.1.16", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.16.tgz", @@ -10626,9 +10522,9 @@ } }, "open": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/open/-/open-7.3.0.tgz", - "integrity": "sha512-mgLwQIx2F/ye9SmbrUkurZCnkoXyXyu9EbHtJZrICjVAJfyMArdHp3KkixGdZx1ZHFPNIwl0DDM1dFFqXbTLZw==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", "requires": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" @@ -10684,11 +10580,6 @@ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, "p-each-series": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", @@ -12331,10 +12222,18 @@ "whatwg-fetch": "^3.4.1" } }, + "react-bootstrap-icons": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/react-bootstrap-icons/-/react-bootstrap-icons-1.4.0.tgz", + "integrity": "sha512-rxT8IxIU3Cnnj4y+rDJvlj5qITNfQP0jdw0e1gGCuyNDQDxvRvrA6QEFSLmWBgMqC/hig3CnZ+Snx2GwXbPxmQ==", + "requires": { + "prop-types": "^15.7.2" + } + }, "react-dev-utils": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.0.tgz", - "integrity": "sha512-uIZTUZXB5tbiM/0auUkLVjWhZGM7DSI304iGunyhA9m985iIDVXd9I4z6MkNa9jeLzeUJbU9A7TUNrcbXAahxw==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz", + "integrity": "sha512-dx0LvIGHcOPtKbeiSUM4jqpBl3TcY7CDjZdfOIcKeznE7BWr9dg0iPG90G5yfVQ+p/rGNMXdbfStvzQZEVEi4A==", "requires": { "@babel/code-frame": "7.10.4", "address": "1.1.2", @@ -12349,13 +12248,13 @@ "global-modules": "2.0.0", "globby": "11.0.1", "gzip-size": "5.1.1", - "immer": "7.0.9", - "inquirer": "7.3.3", + "immer": "8.0.1", "is-root": "2.1.0", "loader-utils": "2.0.0", "open": "^7.0.2", "pkg-up": "3.1.0", - "react-error-overlay": "^6.0.8", + "prompts": "2.4.0", + "react-error-overlay": "^6.0.9", "recursive-readdir": "2.2.2", "shell-quote": "1.7.2", "strip-ansi": "6.0.0", @@ -12427,9 +12326,9 @@ } }, "react-error-overlay": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.8.tgz", - "integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw==" + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", + "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==" }, "react-is": { "version": "16.13.1", @@ -12441,6 +12340,52 @@ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.8.3.tgz", "integrity": "sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==" }, + "react-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", + "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + } + } + } + }, + "react-router-dom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", + "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "requires": { + "@babel/runtime": "^7.1.2", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.2.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, "react-scripts": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-4.0.0.tgz", @@ -12896,6 +12841,11 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -12971,15 +12921,6 @@ } } }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -13121,11 +13062,6 @@ "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==" }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" - }, "run-parallel": { "version": "1.1.10", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", @@ -13139,14 +13075,6 @@ "aproba": "^1.1.1" } }, - "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", - "requires": { - "tslib": "^1.9.0" - } - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -14639,11 +14567,6 @@ "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==" }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -14695,13 +14618,15 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "~1.0.2" - } + "tiny-invariant": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", + "integrity": "sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, "tmpl": { "version": "1.0.4", @@ -14875,6 +14800,11 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==" + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -15143,6 +15073,11 @@ "spdx-expression-parse": "^3.0.0" } }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -16609,9 +16544,9 @@ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, "yallist": { "version": "4.0.0", diff --git a/package.json b/package.json index 16bb883..ab84331 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "vote", + "name": "chat", "version": "0.1.0", "private": true, "dependencies": { @@ -7,9 +7,13 @@ "@testing-library/react": "^11.1.1", "@testing-library/user-event": "^12.2.0", "react": "^17.0.1", + "react-bootstrap-icons": "^1.4.0", "react-dom": "^17.0.1", + "react-router": "^5.2.0", + "react-router-dom": "^5.2.0", "react-scripts": "4.0.0", "styled-components": "^5.2.1", + "typescript": "^4.2.4", "web-vitals": "^0.2.4" }, "scripts": { diff --git a/public/babodog.jpg b/public/babodog.jpg new file mode 100644 index 0000000..e4618b1 Binary files /dev/null and b/public/babodog.jpg differ diff --git a/public/index.html b/public/index.html index df8f5de..854fba8 100644 --- a/public/index.html +++ b/public/index.html @@ -24,7 +24,7 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> - 12기 프론트 투표 + React Chat diff --git a/public/myphoto.jpg b/public/myphoto.jpg new file mode 100644 index 0000000..8b15eb5 Binary files /dev/null and b/public/myphoto.jpg differ diff --git a/src/App.js b/src/App.js index db2f98a..8c38379 100644 --- a/src/App.js +++ b/src/App.js @@ -1,10 +1,245 @@ -import React from 'react'; +import React, { useState } from 'react'; +import styled from 'styled-components'; + +import ProfileContainer from './ProfileContainer'; +import ChatList from './ChatList'; +import ChatInput from './ChatInput'; + +import { BrowserRouter, Route, Switch, Redirect, Link } from 'react-router-dom'; +import FriendList from './FriendList'; +import RoomList from './RoomList'; +import Settings from './Settings'; + +const initialChatData = [ + { + chatId: 1, + chatText: '미션 다햇니', + userId: 0, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 1, + }, + { + chatId: 2, + chatText: '아니ㅎㅎ', + userId: 1, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 1, + }, + { + chatId: 1, + chatText: '미션 다햇니', + userId: 0, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 2, + }, + { + chatId: 2, + chatText: '아니ㅎㅎ', + userId: 2, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 2, + }, + { + chatId: 1, + chatText: '미션 다햇니', + userId: 0, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 3, + }, + { + chatId: 2, + chatText: '아니ㅎㅎ', + userId: 3, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 3, + }, + { + chatId: 1, + chatText: '미션 다햇니', + userId: 0, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 4, + }, + { + chatId: 2, + chatText: '아니ㅎㅎ', + userId: 4, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 4, + }, + { + chatId: 1, + chatText: '미션 다햇니', + userId: 0, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 5, + }, + { + chatId: 2, + chatText: '아니ㅎㅎ', + userId: 5, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 5, + }, + { + chatId: 1, + chatText: '미션 다햇니', + userId: 6, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 6, + }, + { + chatId: 2, + chatText: '아니ㅎㅎ', + userId: 0, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 6, + }, + { + chatId: 1, + chatText: '미션 다햇니', + userId: 7, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 7, + }, + { + chatId: 2, + chatText: '아니ㅎㅎ', + userId: 0, + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + roomId: 7, + }, +]; + +const initialusers = [ + { + id: 0, + name: '정윤선', + profileImgSrc: process.env.PUBLIC_URL + '/myphoto.jpg', + }, + { + id: 1, + name: '김선종', + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + }, + { + id: 2, + name: '김영우', + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + }, + { + id: 3, + name: '박예진', + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + }, + { + id: 4, + name: '안건희', + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + }, + { + id: 5, + name: '이소정', + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + }, + { + id: 6, + name: '이승범', + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + }, + { + id: 7, + name: '이호연', + profileImgSrc: process.env.PUBLIC_URL + '/babodog.jpg', + }, +]; function App() { + const [messages, setMessages] = useState(initialChatData); + const [rooms, setRooms] = useState([]); + const [currentUser, setCurrentUser] = useState(initialusers[0]); + + function toggleCurrentUser(roomId) { + if (currentUser === initialusers[0]) { + setCurrentUser(initialusers[roomId]); + } else { + setCurrentUser(initialusers[0]); + } + } + + function addChatData(message, roomId) { + setMessages( + messages.concat([ + { + chatId: messages.length, + chatText: message, + userId: currentUser.id, + profileImgSrc: currentUser.profileImgSrc, + roomId: roomId, + }, + ]) + ); + } + + // function createRoom(friendId) { + // setRooms((prevRooms) => { + // let newRooms = prevRooms; + // newRooms.push({ + // roomId: rooms.length, + // participants: [friendId, currentUser.id], + // }); + // return newRooms; + // }); + // } + return ( -
12기 프론트엔드 개발팀장 투표 ^.^ -
+ + + + + + {' '} + {/* 이부분은 사용자에게 보이는 주소창에 들어가는 부분! */} + + + + + {' '} + {/* :id 는 유저가 주소창에 입력한 값을 불러오는 곳이다 + (줌 방 번호같은 느낌) + 만약 여러개의 parameter 를 만들고 싶으면 + /:id/:melon/:peach 이런식으루 쓰면 된다!} */} + + + + + + + + + + {/* 만약 이걸 제일 처음에 넣고 싶으면 + exact path="/" 라고 넣어주면 된다! */} + {/* Switch가 없으면 루트에 일치하는 모든 것들을 + 불러오지만 Switch를 넣으면 일치하는 첫번째 루트만 + 불러온다. 따라서 Switch가 없으면 /를 마지막에 넣어도 + 소용이 없다. */} + + + + + ); } +const Container = styled.div` + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; +`; + export default App; diff --git a/src/ChatInput.js b/src/ChatInput.js new file mode 100644 index 0000000..ffa303b --- /dev/null +++ b/src/ChatInput.js @@ -0,0 +1,59 @@ +import { useState } from 'react'; +import { useParams } from 'react-router-dom'; +import styled from 'styled-components'; + +const Container = styled.div` + display: flex; + flex-direction: row; + + height: 60px; +`; + +const ChatSendInput = styled.input` + flex-grow: 5; +`; + +const SubmitButton = styled.button` + flex-grow: 1; +`; + +function ChatInput(props) { + const [inputValue, setInputValue] = useState(''); + + const { addChatData } = props; + + const { roomId } = useParams(); // App.js에서 Route path="/room/:id에서 불러온 parameters 중에 id!" + + function handleChange(e) { + setInputValue(e.target.value); // inputValue를 e.target.value로 업데이트 + } + + function handleClick() { + if (inputValue !== '') { + addChatData(inputValue, roomId); + setInputValue(''); + } + } + + function handleKeyPress(e) { + if (e.code === 'Enter' && !e.isComposing) { + handleClick(); + } + } + + return ( + + + 전송 + + ); +} +// value는 원래 html에서 Input이라는 element에 있는 attribute이다. +// 여기서 value는 원래 props인데 styled.component의 기능 중 같은 이름이면 attribute로 처리되는 기능때문에 attribute로 처리된다. +// styledComponent로 HTML attribute와 같은 이름을 가진 props를 넘겨주면, 그걸 자동으로 html attribute로 넘겨준다. + +export default ChatInput; diff --git a/src/ChatItem.js b/src/ChatItem.js new file mode 100644 index 0000000..8d5df1a --- /dev/null +++ b/src/ChatItem.js @@ -0,0 +1,49 @@ +import styled from 'styled-components'; + +const ChatBox = styled.div` + display: flex; + flex-direction: row; + margin-bottom: 15px; +`; +// const name = "정윤선" +// const Text = `저의 이름은 ${name}입니다.` + +const Photo = styled.img` + width: 50px; + height: 50px; + border-radius: 50%; +`; + +const ChatText = styled.div` + border: 1px solid black; + border-radius: 10px; + padding: 10px; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: flex-start; + margin: 0 10px; +`; + +export default function ChatItem(props) { + // props = { item: item } + + // props.item = { + // chatId: 1, + // chatText: '안녕!!', + // userId: 1, + // profileImg: process.env.PUBLIC_URL + '/logo512.png', + // } + + const { chatText, profileImgSrc, userId } = props.item; + // const {messages} = props; + // const messages = props.messages 둘이 같은거! + // 결론은 const userId = props.item.userId + console.log(props.item.userId===0) + return ( + + + {chatText} + + ); +} diff --git a/src/ChatList.js b/src/ChatList.js new file mode 100644 index 0000000..1c8ffc8 --- /dev/null +++ b/src/ChatList.js @@ -0,0 +1,57 @@ +import styled from 'styled-components'; +import ChatItem from './ChatItem'; +import { useEffect, useRef } from 'react'; +import { useParams } from 'react-router-dom'; + +const Container = styled.div` + display: flex; + flex-direction: column; + padding: 15px; + flex-grow: 1; + overflow-y: scroll; +`; + +// ChatList = ChatItem 들 다 모아놓은 곳 +// ChatItem = 프사+메세지 포함하는 상자 + +function ChatList(props) { + const { messages } = props; + // const messages = props.messages + // props 중에서 messages가 배열인것! + + const containerRef = useRef(null); + + const params = useParams(); // App.js에서 Route path="/room/:id에서 불러온 parameters 중에 id!" + + const list = messages + .filter((item) => { + return item.roomId.toString() === params.roomId; + }) + .map((item) => { + return ; + }); + // filter는 조건에 대한 참/거짓을 return하고 참인 원소들로 새로운 배열을 출력한다. 거기에 바로 map 함수를 건 것! + + // function mapItem(item) { + // return > + // } + + // const list = messages.map(mapItem); + + // function map(_function) { + // return + // } + + useEffect( + function () { + containerRef.current.scrollBy(0, containerRef.current.scrollHeight); + }, + [messages] + ); + // useEffect(무엇을, 언제(배열형태가 들어있고 이 배열에 변화가 생길 때 실행된다)); + // 배열안에 함수도 넣을 수 있다 + + return {list}; +} + +export default ChatList; diff --git a/src/FriendItem.js b/src/FriendItem.js new file mode 100644 index 0000000..15b9ec4 --- /dev/null +++ b/src/FriendItem.js @@ -0,0 +1,49 @@ +//import { useHistory } from 'react-router'; +import { Link } from 'react-router-dom'; +import styled from 'styled-components'; + +const Container = styled.div` + display: flex; + flex-direction: row; + align-items: center; + padding: 10px; + &:first-of-type { + border-bottom: 1px solid gray; + } +`; + +const Photo = styled.img` + width: 45px; + height: 45px; + border-radius: 18px; + margin: 5px; +`; + +const UserName = styled.div` + margin-left: 10px; + font-weight: bold; +`; + +// App.js에 추가하면 안되나... +function FriendItem(props) { + if (props.user.id === 0) { + //user가 나 자신(0)이면 Link component를 렌더하지 않는다 + return ( + + + {props.user.name} + + ); + } else { + return ( + + + + {props.user.name} + + + ); + } +} + +export default FriendItem; diff --git a/src/FriendList.js b/src/FriendList.js new file mode 100644 index 0000000..2f012cf --- /dev/null +++ b/src/FriendList.js @@ -0,0 +1,83 @@ +import React, { useState, useEffect } from 'react'; +import styled from 'styled-components'; +import Header from './Header'; +import NavigationBar from './NavigationBar'; +import FriendItem from './FriendItem'; + +const Container = styled.div` + width: 100vw; + height: 100vh; + display: flex; + flex-direction: row; +`; + +const RightFriendsList = styled.div` + display: flex; + flex-direction: column; + flex-grow: 6; +`; + +const FriendsListBox = styled.div` + display: flex; + flex-direction: column; + flex-grow: 10; + overflow-y: scroll; +`; + +const StyledSearchBar = styled.div` + padding: 5px 10px; + width: 100%; + & input { + width: 100%; + border-radius: 3px; + border: none; + background: lightgray; + color: black; + padding: 10px 10px; + font-size: 1em; + } +`; + +function FriendList(props) { + const { FriendListData } = props; + const [searchQuery, setSearchQuery] = useState(''); + const [filteredFriendList, setFilteredFriendList] = useState(FriendListData); + + useEffect(() => { + setFilteredFriendList(() => { + if (searchQuery === '') { + return FriendListData; + } else { + return FriendListData.filter((user) => { + return user.name.includes(searchQuery); + }); + } + }); + }, [searchQuery, FriendListData]); + + const list = filteredFriendList.map((user) => { + return ; + }); + + return ( + + + +
+ + { + setSearchQuery(e.target.value); + }} + /> + + {list} +
+
+ ); +} + +export default FriendList; diff --git a/src/Header.js b/src/Header.js new file mode 100644 index 0000000..b56cb47 --- /dev/null +++ b/src/Header.js @@ -0,0 +1,25 @@ +import React from 'react'; +import { Switch, Route } from 'react-router-dom'; +import styled from 'styled-components'; + +const StyledHeader = styled.div` + display: flex; + flex-direction: row; + padding: 20px 15px 15px 15px; + font-size: 1.4em; + font-weight: bold; +`; + +function Header() { + return ( + + + 친구 + 채팅 + 설정 + + + ); +} + +export default Header; diff --git a/src/NavigationBar.js b/src/NavigationBar.js new file mode 100644 index 0000000..08d4852 --- /dev/null +++ b/src/NavigationBar.js @@ -0,0 +1,78 @@ +import React from 'react'; +import styled from 'styled-components'; +import { PersonFill, ChatFill, ThreeDots, EmojiSmile, Bell, Gear} from 'react-bootstrap-icons'; +import { Link } from 'react-router-dom'; + +const StyledNavigationBar = styled.div` +display: flex; +flex-direction: column; +justify-content: space-between; +align-items: center; +width: 100px; +background-color: #dfdfdf; +`; + +const StyledAboveBar = styled.div` +display: flex; +flex-direction: column; +align-items: center; +font-size: 2.3em; +padding-top: 50px; +& * { + color: gray; + margin: 5px; + padding: 0; +} +`; + +const StyledUnderBar = styled.div` +display: flex; +flex-direction: column; +font-size: 2em; +padding-bottom: 50px; +& * { + color: gray; + margin: 12px; + padding: 0; +} +`; + +function AboveBar() { + return ( + <> + + + + + + + + + ) +} + +function UnderBar() { + return ( + <> + + + + + ) +} + +function NavigationBar() { + + return ( + + + + + + + + + ) +}; + +export default NavigationBar; \ No newline at end of file diff --git a/src/ProfileContainer.js b/src/ProfileContainer.js new file mode 100644 index 0000000..97d06ce --- /dev/null +++ b/src/ProfileContainer.js @@ -0,0 +1,54 @@ +import { useParams } from 'react-router'; +import styled from 'styled-components'; + +const Container = styled.div` + background-color: rgb(245, 245, 245); + display: flex; + flex-direction: row; + align-item: center; + border-bottom: 1px solid black; +`; + +const Photo = styled.img` + width: 60px; + height: 60px; + border-radius: 40px; + border: 1px solid black; + margin: 10px; +`; + +const UserInfoContainer = styled.div` + margin-left: 10px; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; +`; + +const UserName = styled.div` + font-size: 1.2em; + margin-bottom: 3px; + font-weight: bold; +`; + +const UserStatus = styled.div``; + +// App.js에 추가하면 안되나... +function ProfileContainer(props) { + const { roomId } = useParams(); + + function handleClick() { + props.toggleCurrentUser(roomId); + } + return ( + + + + {props.currentUser.name} + 현재 활동 중 + + + ); +} + +export default ProfileContainer; diff --git a/src/RoomItem.js b/src/RoomItem.js new file mode 100644 index 0000000..4b646cf --- /dev/null +++ b/src/RoomItem.js @@ -0,0 +1,49 @@ +//import { useHistory } from 'react-router'; +import { Link } from 'react-router-dom'; +import styled from 'styled-components'; + +const Container = styled.div` + display: flex; + flex-direction: row; + align-items: center; + padding: 10px; + border-bottom: 1px solid gray; +`; + +const ChatInfo = styled.div` + display: flex; + flex-direction: column; +`; + +const Photo = styled.img` + width: 45px; + height: 45px; + border-radius: 18px; + margin: 5px; +`; + +const UserName = styled.div` + margin: 0 0 3px 10px; + font-weight: bold; +`; + +const LastMessage = styled.div` + margin-left: 10px; +`; + +// App.js에 추가하면 안되나... +function RoomItem(props) { + return ( + + + + + {props.user.name} + {props.lastMessage} + + + + ); +} + +export default RoomItem; diff --git a/src/RoomList.js b/src/RoomList.js new file mode 100644 index 0000000..a61536e --- /dev/null +++ b/src/RoomList.js @@ -0,0 +1,94 @@ +import React, { useEffect, useState } from 'react'; +import styled from 'styled-components'; +import Header from './Header'; +import NavigationBar from './NavigationBar'; +import RoomItem from './RoomItem'; + +const StyledRoomList = styled.div` + width: 100vw; + height: 100vh; + display: flex; + flex-direction: row; +`; + +const RoomListBox = styled.div` + display: flex; + flex-direction: column; + width: 100%; + max-height: 100vh; + overflow-y: scroll; +`; + +const StyledSearchBar = styled.div` + padding: 5px 10px; + width: 100%; + & input { + width: 100%; + border-radius: 3px; + border: none; + background: lightgray; + color: black; + padding: 10px 10px; + font-size: 1em; + } +`; + +export default function RoomList(props) { + const { initialusers, messages } = props; + // const initialusers = props.initialusers; + // const messages = props.messages; + const [searchQuery, setSearchQuery] = useState(''); + const [filteredUsers, setFilteredUsers] = useState(initialusers); + + useEffect(() => { + setFilteredUsers(() => { + if (searchQuery === '') { + return initialusers; + } else { + return initialusers.filter((user) => { + return user.name.includes(searchQuery); + }); + } + }); + }, [searchQuery, initialusers]); + + const list = filteredUsers + .filter((user) => { + return user.id !== 0; + }) + .map((user, idx) => { + const messagesWithUser = messages.filter((msg) => { + return msg.roomId === user.id; + }); + // 지금 나와 대화하는 상대의 messages만을 불러오기 위한 문장 + if (messagesWithUser.length === 0) return ''; + // 아직 대화 안 한 상대는 채팅방을 만들지 않게 하기 위한 문장 + return ( + + ); + }); + + return ( + + + +
+ + { + setSearchQuery(e.target.value); + }} + /> + + {list} + + + ); +} diff --git a/src/Settings.js b/src/Settings.js new file mode 100644 index 0000000..6be2114 --- /dev/null +++ b/src/Settings.js @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function Settings() { + return
Settings
; +} diff --git a/src/index.js b/src/index.js index c1f31c5..af12b65 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; +import './styles/global.css'; ReactDOM.render( diff --git a/src/styles/global.css b/src/styles/global.css new file mode 100644 index 0000000..53210e3 --- /dev/null +++ b/src/styles/global.css @@ -0,0 +1,20 @@ +html, +body { + margin: 0; +} + +* { + box-sizing: border-box; + /* 이거 안해주면 원래는 padding 안쪽의 content에만 크기가 적용되고 padding을 더해주면 너비와 높이에 더한 값을 화면에 그린다. + 근데 이거 넣어주면 padding을 넣든 margin을 넣든 기준이 border이 된다. + content-box는 기본 CSS 박스 크기 결정법을 사용합니다. + 요소의 너비를 100 픽셀로 설정하면 콘텐츠 영역이 100 픽셀 너비를 가지고, 테두리와 안쪽 여백은 이에 더해집니다. + border-box는 테두리와 안쪽 여백의 크기도 요소의 크기로 고려합니다. + 너비를 100 픽셀로 설정하고 테두리와 안쪽 여백을 추가하면, 콘텐츠 영역이 줄어들어 총 너비 100 픽셀을 유지합니다. + 대부분의 경우 이 편이 크기를 조절할 때 쉽습니다.*/ +} + +a { + text-decoration: none; + color: inherit; +}