diff --git a/.eslintrc.json b/.eslintrc.json index 89ffe83..e5659dd 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -32,6 +32,7 @@ "rules": { "react/jsx-wrap-multilines": ["error", { "prop": "ignore" }], "react/jsx-props-no-spreading": "off", + "react/no-array-index-key": "off", "object-curly-newline": ["off"], "implicit-arrow-linebreak": ["off"], "max-len": ["error", 120], diff --git a/package-lock.json b/package-lock.json index 9e7820e..3ea7443 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,8 @@ "@cincoders/cinnamon": "^1.0.2", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^5.14.1", + "@mui/lab": "^5.0.0-alpha.137", "@mui/material": "^5.13.5", "papaparse": "^5.4.1", "react": "^18.1.0", @@ -77,6 +79,84 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/cli": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.22.9.tgz", + "integrity": "sha512-nb2O7AThqRo7/E53EGiuAkMaRbb7J5Qp3RvN+dmua1U+kydm0oznkhqbTEG15yk26G/C3yL6OdZjzgl+DMXVVA==", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.2.0", + "make-dir": "^2.1.0", + "slash": "^2.0.0" + }, + "bin": { + "babel": "bin/babel.js", + "babel-external-helpers": "bin/babel-external-helpers.js" + }, + "engines": { + "node": ">=6.9.0" + }, + "optionalDependencies": { + "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3", + "chokidar": "^3.4.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/cli/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "peer": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@babel/cli/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "peer": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/cli/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/cli/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/cli/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/@babel/code-frame": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", @@ -567,6 +647,21 @@ "@babel/core": "^7.13.0" } }, + "node_modules/@babel/plugin-external-helpers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-external-helpers/-/plugin-external-helpers-7.22.5.tgz", + "integrity": "sha512-ngnNEWxmykPk82mH4ajZT0qTztr3Je6hrMuKAslZVM8G1YZTENJSYwrIGtt6KOtznug3exmAtF4so/nPqJuA4A==", + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-proposal-class-properties": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", @@ -630,6 +725,25 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "peer": true, + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-proposal-optional-chaining": { "version": "7.21.0", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", @@ -2092,6 +2206,40 @@ "react-transition-group": "^4.4.2" } }, + "node_modules/@cincoders/cinnamon/node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "node_modules/@cincoders/cinnamon/node_modules/styled-components": { + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", + "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-is": ">= 16.8.0" + } + }, "node_modules/@csstools/normalize.css": { "version": "12.0.0", "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.0.0.tgz", @@ -3438,6 +3586,84 @@ } } }, + "node_modules/@mui/lab": { + "version": "5.0.0-alpha.137", + "resolved": "https://registry.npmjs.org/@mui/lab/-/lab-5.0.0-alpha.137.tgz", + "integrity": "sha512-bHfcfti9/GnB657QpTdlK1fc9gjkP3SC+NrXyb9NCr0rT5Cq7TEkBGXyY5wGUSCyHR3CrMvchkIsfG5sH/NJ9A==", + "dependencies": { + "@babel/runtime": "^7.22.6", + "@mui/base": "5.0.0-beta.8", + "@mui/system": "^5.14.1", + "@mui/types": "^7.2.4", + "@mui/utils": "^5.14.1", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/lab/node_modules/@mui/base": { + "version": "5.0.0-beta.8", + "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.8.tgz", + "integrity": "sha512-b4vVjMZx5KzzEMf4arXKoeV5ZegAMOoPwoy1vfUBwhvXc2QtaaAyBp50U7OA2L06Leubc1A+lEp3eqwZoFn87g==", + "dependencies": { + "@babel/runtime": "^7.22.6", + "@emotion/is-prop-valid": "^1.2.1", + "@mui/types": "^7.2.4", + "@mui/utils": "^5.14.1", + "@popperjs/core": "^2.11.8", + "clsx": "^1.2.1", + "prop-types": "^15.8.1", + "react-is": "^18.2.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/lab/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, "node_modules/@mui/material": { "version": "5.13.6", "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.13.6.tgz", @@ -3488,12 +3714,12 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/@mui/private-theming": { - "version": "5.13.1", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.1.tgz", - "integrity": "sha512-HW4npLUD9BAkVppOUZHeO1FOKUJWAwbpy0VQoGe3McUYTlck1HezGHQCfBQ5S/Nszi7EViqiimECVl9xi+/WjQ==", + "version": "5.13.7", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.7.tgz", + "integrity": "sha512-qbSr+udcij5F9dKhGX7fEdx2drXchq7htLNr2Qg2Ma+WJ6q0ERlEqGSBiPiVDJkptcjeVL4DGmcf1wl5+vD4EA==", "dependencies": { - "@babel/runtime": "^7.21.0", - "@mui/utils": "^5.13.1", + "@babel/runtime": "^7.22.5", + "@mui/utils": "^5.13.7", "prop-types": "^15.8.1" }, "engines": { @@ -3545,15 +3771,15 @@ } }, "node_modules/@mui/system": { - "version": "5.13.6", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.13.6.tgz", - "integrity": "sha512-G3Xr28uLqU3DyF6r2LQkHGw/ku4P0AHzlKVe7FGXOPl7X1u+hoe2xxj8Vdiq/69II/mh9OP21i38yBWgWb7WgQ==", + "version": "5.14.1", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.1.tgz", + "integrity": "sha512-u+xlsU34Jdkgx1CxmBnIC4Y08uPdVX5iEd3S/1dggDFtOGp+Lj8xmKRJAQ8PJOOJLOh8pDwaZx4AwXikL4l1QA==", "dependencies": { - "@babel/runtime": "^7.22.5", - "@mui/private-theming": "^5.13.1", + "@babel/runtime": "^7.22.6", + "@mui/private-theming": "^5.13.7", "@mui/styled-engine": "^5.13.2", "@mui/types": "^7.2.4", - "@mui/utils": "^5.13.6", + "@mui/utils": "^5.14.1", "clsx": "^1.2.1", "csstype": "^3.1.2", "prop-types": "^15.8.1" @@ -3597,13 +3823,13 @@ } }, "node_modules/@mui/utils": { - "version": "5.13.6", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.6.tgz", - "integrity": "sha512-ggNlxl5NPSbp+kNcQLmSig6WVB0Id+4gOxhx644987v4fsji+CSXc+MFYLocFB/x4oHtzCUlSzbVHlJfP/fXoQ==", + "version": "5.14.1", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.1.tgz", + "integrity": "sha512-39KHKK2JeqRmuUcLDLwM+c2XfVC136C5/yUyQXmO2PVbOb2Bol4KxtkssEqCbTwg87PSCG3f1Tb0keRsK7cVGw==", "dependencies": { - "@babel/runtime": "^7.22.5", + "@babel/runtime": "^7.22.6", "@types/prop-types": "^15.7.5", - "@types/react-is": "^18.2.0", + "@types/react-is": "^18.2.1", "prop-types": "^15.8.1", "react-is": "^18.2.0" }, @@ -3623,6 +3849,13 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, + "node_modules/@nicolo-ribaudo/chokidar-2": { + "version": "2.1.8-no-fsevents.3", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz", + "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==", + "optional": true, + "peer": true + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -4817,6 +5050,12 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, + "node_modules/@types/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-n4sx2bqL0mW1tvDf/loQ+aMX7GQD3lc3fkCMC55VFNDu/vBOabO+LTIeXKM14xK0ppk5TUGcWRjiSpIlUpghKw==", + "peer": true + }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.6", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.6.tgz", @@ -9299,6 +9538,12 @@ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==" }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "peer": true + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -16932,38 +17177,54 @@ } }, "node_modules/styled-components": { - "version": "5.3.11", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz", - "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.0.5.tgz", + "integrity": "sha512-308zi5o7LrA9cVaP4nPD0TaUpOjGPePkAUFb/OGB0xRI3I9ozpW5UyASvRVi9wJcYASG+Y3mLDLDUZC7nqzimw==", + "peer": true, "dependencies": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/traverse": "^7.4.5", - "@emotion/is-prop-valid": "^1.1.0", - "@emotion/stylis": "^0.8.4", - "@emotion/unitless": "^0.7.4", - "babel-plugin-styled-components": ">= 1.12.0", - "css-to-react-native": "^3.0.0", - "hoist-non-react-statics": "^3.0.0", + "@babel/cli": "^7.21.0", + "@babel/core": "^7.21.0", + "@babel/helper-module-imports": "^7.18.6", + "@babel/plugin-external-helpers": "^7.18.6", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.20.7", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@babel/traverse": "^7.21.2", + "@emotion/is-prop-valid": "^1.2.1", + "@emotion/unitless": "^0.8.0", + "@types/stylis": "^4.0.2", + "css-to-react-native": "^3.2.0", + "csstype": "^3.1.2", + "postcss": "^8.4.23", "shallowequal": "^1.1.0", - "supports-color": "^5.5.0" + "stylis": "^4.3.0", + "tslib": "^2.5.0" }, "engines": { - "node": ">=10" + "node": ">= 16" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/styled-components" }, "peerDependencies": { + "babel-plugin-styled-components": ">= 2", "react": ">= 16.8.0", - "react-dom": ">= 16.8.0", - "react-is": ">= 16.8.0" + "react-dom": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "babel-plugin-styled-components": { + "optional": true + } } }, - "node_modules/styled-components/node_modules/@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + "node_modules/styled-components/node_modules/stylis": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", + "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==", + "peer": true }, "node_modules/stylehacks": { "version": "5.1.1", diff --git a/package.json b/package.json index cc99680..6c1b532 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,8 @@ "@cincoders/cinnamon": "^1.0.2", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", + "@mui/icons-material": "^5.14.1", + "@mui/lab": "^5.0.0-alpha.137", "@mui/material": "^5.13.5", "papaparse": "^5.4.1", "react": "^18.1.0", diff --git a/src/components/Conference/index.tsx b/src/components/Conference/index.tsx index 03472cb..759802d 100644 --- a/src/components/Conference/index.tsx +++ b/src/components/Conference/index.tsx @@ -6,6 +6,7 @@ export interface DeadlineProps { conference: string; website: string; conferenceDetail: string; + greatArea: string; area: string; conferenceDates: string; location: string; @@ -18,6 +19,7 @@ export function Conference({ conference, website, conferenceDetail, + greatArea, area, conferenceDates, location, @@ -91,7 +93,7 @@ export function Conference({ {conferenceDetail} - {area} + {`${greatArea} - ${area}`} diff --git a/src/components/Filter/index.tsx b/src/components/Filter/index.tsx index e5bf010..ae31940 100644 --- a/src/components/Filter/index.tsx +++ b/src/components/Filter/index.tsx @@ -4,20 +4,29 @@ import { Conference, DeadlineProps } from '../Conference'; interface FilterProps { deadlines: DeadlineProps[]; + checkedValues: string[]; } -function FilterPage({ deadlines }: FilterProps) { +function FilterPage({ deadlines, checkedValues }: FilterProps) { const [filterText, setFilterText] = useState(''); const handleInputChange = (event: React.ChangeEvent) => { setFilterText(event.target.value); }; - const filteredDeadlines: DeadlineProps[] = deadlines.filter(deadline => + const getCheckedAreaNames = (): string[] => checkedValues.map(nodeId => nodeId.split('_')[1]); + + const filteredDeadlinesByText: DeadlineProps[] = deadlines.filter(deadline => Object.values(deadline).some( value => typeof value === 'string' && value.toLowerCase().includes(filterText.toLowerCase()), ), ); + + const filteredDeadlines: DeadlineProps[] = + checkedValues.length > 0 + ? filteredDeadlinesByText.filter(deadline => getCheckedAreaNames().includes(deadline.area)) + : filteredDeadlinesByText; + return ( void; +} + +function FilterByArea({ deadlines, checkedValues, onCheckedChange }: FilterProps) { + const createTreeData = (deadlinesValue: FilterByAreaDeadlineProps[]) => { + const treeData = new Map(); + deadlinesValue.forEach(deadline => { + const { greatArea, area } = deadline; + if (!treeData.has(greatArea)) { + treeData.set(greatArea, []); + } + if (!treeData.get(greatArea)?.includes(area)) { + treeData.get(greatArea)?.push(area); + } + }); + return treeData; + }; + const treeData = createTreeData(deadlines); + + const toggleChecked = (currentCheckedValues: string[], nodeId: string): string[] => { + const newCheckedValues = [...currentCheckedValues]; + const currentIndex = currentCheckedValues.indexOf(nodeId); + if (currentIndex === -1) { + newCheckedValues.push(nodeId); + } else { + newCheckedValues.splice(currentIndex, 1); + } + + if (treeData.has(nodeId)) { + treeData.get(nodeId)?.forEach(subarea => { + const childNodeId = `${nodeId}_${subarea}`; + if (!newCheckedValues.includes(childNodeId) && newCheckedValues.includes(nodeId)) { + newCheckedValues.push(childNodeId); + } else if (newCheckedValues.includes(childNodeId) && !newCheckedValues.includes(nodeId)) { + newCheckedValues.splice(newCheckedValues.indexOf(childNodeId), 1); + } + newCheckedValues.concat(toggleChecked(newCheckedValues, childNodeId)); + }); + } + + const parentIndex = nodeId.lastIndexOf('_'); + if (parentIndex !== -1) { + const parent = nodeId.substring(0, parentIndex); + const siblings = treeData.get(parent); + const siblingsChecked = siblings?.every(sibling => newCheckedValues.includes(sibling)); + + if (siblingsChecked && !newCheckedValues.includes(parent)) { + newCheckedValues.push(parent); + } else if (!siblingsChecked && newCheckedValues.includes(parent)) { + newCheckedValues.splice(newCheckedValues.indexOf(parent), 1); + } + } + return newCheckedValues; + }; + + const handleCheckboxChange = (event: React.ChangeEvent, nodeId: string) => { + const newCheckedValues = toggleChecked(checkedValues, nodeId); + onCheckedChange(newCheckedValues); + }; + + return ( +
+ Filter by Areas + } + defaultExpandIcon={} + > + {treeData.size > 0 && + Array.from(treeData) + .sort((a, b) => a[0].localeCompare(b[0])) + .map(([greatArea, areas]) => ( + + handleCheckboxChange(e, greatArea)} + /> + {greatArea} + + } + > + {areas.map(area => { + const childNodeId = `${greatArea}_${area}`; + return ( + + handleCheckboxChange(e, childNodeId)} + /> + {area} + + } + /> + ); + })} + + ))} + +
+ ); +} + +export default FilterByArea; diff --git a/src/components/FilterByArea/styles.tsx b/src/components/FilterByArea/styles.tsx new file mode 100644 index 0000000..2da6ede --- /dev/null +++ b/src/components/FilterByArea/styles.tsx @@ -0,0 +1,5 @@ +import { styled } from '@mui/material/styles'; + +export const StyledTreeItemLabel = styled('div')({ + fontSize: '14px', +}); diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index 222ed99..1a58dd7 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -1,8 +1,10 @@ import { Box, CircularProgress, Link, Typography } from '@mui/material'; import Papa from 'papaparse'; import { useEffect, useState } from 'react'; -import { DeadlineProps } from '../../components/Conference'; import FilterPage from '../../components/Filter'; +import FilterByArea from '../../components/FilterByArea'; +import { FilterContainer, FilterByAreaContainer } from './styles'; +import { DeadlineProps } from '../../components/Conference'; function compare(a: DeadlineProps, b: DeadlineProps) { if (a.submissionDeadline < b.submissionDeadline) { @@ -23,6 +25,7 @@ function compare(a: DeadlineProps, b: DeadlineProps) { function Home() { const [deadlines, setDeadlines] = useState([]); const [loading, setLoading] = useState(true); + const [checkedValues, setCheckedValues] = useState([]); useEffect(() => { const sheetUrl = @@ -33,11 +36,12 @@ function Home() { complete(results) { const rawDeadlines: string[][] = results.data as string[][]; const parsedDeadlines = rawDeadlines.map((deadline: string[]) => ({ + greatArea: deadline[rawDeadlines[0].indexOf('GreatArea')], + area: deadline[rawDeadlines[0].indexOf('Area')], deadlineId: deadline[rawDeadlines[0].indexOf('DeadlineId')], conference: deadline[rawDeadlines[0].indexOf('Conference')], website: deadline[rawDeadlines[0].indexOf('WebSite')], conferenceDetail: deadline[rawDeadlines[0].indexOf('ConferenceDetail')], - area: `${deadline[rawDeadlines[0].indexOf('GreatArea')]} - ${deadline[rawDeadlines[0].indexOf('Area')]}`, conferenceDates: deadline[rawDeadlines[0].indexOf('ConferenceDates')], location: deadline[rawDeadlines[0].indexOf('Location')], submissionDeadline: new Date(deadline[rawDeadlines[0].indexOf('DeadlineISO')]), @@ -52,6 +56,10 @@ function Home() { }); }, []); + const handleCheckedChange = (checkedChangedValues: string[]) => { + setCheckedValues(checkedChangedValues); + }; + return ( <> @@ -65,7 +73,15 @@ function Home() {
)} - {!loading && } + {!loading && ( + + + + + + + + )} ); } diff --git a/src/pages/Home/styles.tsx b/src/pages/Home/styles.tsx new file mode 100644 index 0000000..73f283c --- /dev/null +++ b/src/pages/Home/styles.tsx @@ -0,0 +1,14 @@ +import { styled } from '@mui/material'; + +export const FilterContainer = styled('div')({ + display: 'flex', + flexDirection: 'row', + flexGrow: 1, + marginTop: '20px', + width: '100%', +}); + +export const FilterByAreaContainer = styled('div')({ + width: '20%', + marginRight: '20px', +});