diff --git a/package-lock.json b/package-lock.json index 9fa33281..39c78bfd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "express": "^4.17.1", "express-fileupload": "^1.2.1", "fs": "^0.0.1-security", + "fuse.js": "^6.4.6", "jsonwebtoken": "^8.5.1", "mongodb": "^3.5.9", "mongoose": "^5.9.20", @@ -9092,6 +9093,14 @@ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, + "node_modules/fuse.js": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.4.6.tgz", + "integrity": "sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw==", + "engines": { + "node": ">=10" + } + }, "node_modules/gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -30604,6 +30613,11 @@ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, + "fuse.js": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.4.6.tgz", + "integrity": "sha512-/gYxR/0VpXmWSfZOIPS3rWwU8SHgsRTwWuXhyb2O6s7aRuVtHtxCkR33bNYu3wyLyNx/Wpv0vU7FZy8Vj53VNw==" + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", diff --git a/package.json b/package.json index 3514c52e..1047cc8f 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "express": "^4.17.1", "express-fileupload": "^1.2.1", "fs": "^0.0.1-security", + "fuse.js": "^6.4.6", "jsonwebtoken": "^8.5.1", "mongodb": "^3.5.9", "mongoose": "^5.9.20", diff --git a/src/containers/AdminDashboard/AdminDashboard.css b/src/containers/AdminDashboard/AdminDashboard.css index b2b8b2bf..16bf0685 100644 --- a/src/containers/AdminDashboard/AdminDashboard.css +++ b/src/containers/AdminDashboard/AdminDashboard.css @@ -126,6 +126,9 @@ border: solid 1px var(--color-red); } +.AdminDashboard .dropdown-select { + margin: .5rem; +} .AdminDashboard .dashboard-section-title { font-weight: 800; margin: 2rem 0 1rem; diff --git a/src/containers/AdminDashboard/AdminDashboard.js b/src/containers/AdminDashboard/AdminDashboard.js index d3efe817..b270ee46 100644 --- a/src/containers/AdminDashboard/AdminDashboard.js +++ b/src/containers/AdminDashboard/AdminDashboard.js @@ -11,6 +11,7 @@ import { deleteQuestionnaireResponse, } from '../../sendRequest/apis'; import { getAuthToken } from '../../utilities/auth_utils'; +import { searchArrayObjects } from '../../utilities/search_array'; import './AdminDashboard.css'; import { languageOptions, workshopTitle } from '../../data/LanguageOptions'; import Navbar from '../../compositions/Navbar/Navbar'; @@ -37,6 +38,8 @@ const AdminDashboard = (props) => { const [loading, setLoading] = useState(true); const [createdOrder, setCreatedOrder] = useState(true); const [updatedOrder, setUpdatedOrder] = useState(true); + const [filterBy, setFilterBy] = useState('full_name'); + const [searchTerm, setSearchTerm] = useState(''); useEffect(() => { setLoading(true); const jwt = getAuthToken(); @@ -339,7 +342,13 @@ const AdminDashboard = (props) => { }; const responsesMarkup = useMemo(() => { - return questionnaireResponses.map((response, index) => { + let filterQuestionnaireResponses = searchArrayObjects( + questionnaireResponses, + `questionnaireResponse.${filterBy}`, + searchTerm, + 3 + ); + return filterQuestionnaireResponses.map((response, index) => { const { questionnaireResponse = {} } = response; const fullLangText = languageOptions.find( (item) => item.code === questionnaireResponse['languageCode'] @@ -487,6 +496,8 @@ const AdminDashboard = (props) => { downloadOrder, createdOrder, updatedOrder, + filterBy, + searchTerm, ]); const responsesTable = ( @@ -687,6 +698,27 @@ const AdminDashboard = (props) => { />
+
+ setSearchTerm(e.target.value)} + type="text" + name="name" + /> + +

Details

{responsesTable} diff --git a/src/utilities/search_array.js b/src/utilities/search_array.js new file mode 100644 index 00000000..b3b6ca9e --- /dev/null +++ b/src/utilities/search_array.js @@ -0,0 +1,25 @@ +import Fuse from 'fuse.js'; +/** + * search through an arary of objects for a specifed search string + * objects-array of objects to be filterd + * propertyPath - property to be filtered on, can include sub objects + * searchText - text to search for + * minLength - min length of the match + * @returns the filtered responses from the array + */ +export const searchArrayObjects = ( + objects, + propertyPath, + searchText, + minLength = 3 +) => { + if (!searchText) { + return objects; + } + const fuse = new Fuse(objects, { + keys: [propertyPath], + minMatchCharLength: minLength, + }); + const filterResponse = fuse.search(searchText).map((result) => result.item); + return filterResponse; +};