From 1f1a18d97540f06da95f40dc8f2ffe5fd7203b18 Mon Sep 17 00:00:00 2001 From: matejoslav Date: Mon, 20 Nov 2023 19:53:35 +0000 Subject: [PATCH] added functionality to search therapists by name --- src/services/psychotherapist.service.spec.ts | 13 ++- src/services/psychotherapist.service.ts | 42 +++++++++ src/types/Filter.ts | 2 + src/util/filter-util.ts | 1 + web-app/src/constants/directory.js | 4 + .../src/pages/directory/components/Sidebar.js | 93 ++++++++++++------- .../__snapshots__/Sidebar.spec.js.snap | 91 ++++++++++++++++++ web-app/src/pages/directory/directoryPage.js | 10 +- 8 files changed, 221 insertions(+), 35 deletions(-) diff --git a/src/services/psychotherapist.service.spec.ts b/src/services/psychotherapist.service.spec.ts index cbae754..11a9798 100644 --- a/src/services/psychotherapist.service.spec.ts +++ b/src/services/psychotherapist.service.spec.ts @@ -282,6 +282,7 @@ describe("The psychotherapist service", () => { patientgroups: ["patientGroup"], price: ["price"], legalpersonality: ["legalpersonality"], + name: ["name"], }; await psychotherapistService.getPsychotherapists(mockFilter); @@ -322,7 +323,17 @@ describe("The psychotherapist service", () => { { keys: ["legalpersonality"], include_docs: true } ); - expect(mockView).toHaveBeenCalledTimes(6); + expect(mockView).toHaveBeenCalledWith( + "therapistsDesignDoc", + "therapistsByName", + { + startkey: "name", + endkey: "name" + "\ufff0", + include_docs: true, + } + ); + + expect(mockView).toHaveBeenCalledTimes(7); }); it("should return empty array if the view has returned no rows matching our filter", async () => { diff --git a/src/services/psychotherapist.service.ts b/src/services/psychotherapist.service.ts index 775f4da..5e723cc 100644 --- a/src/services/psychotherapist.service.ts +++ b/src/services/psychotherapist.service.ts @@ -11,6 +11,32 @@ import { InternalServerError } from "routing-controllers"; import { CLOUDANT_PSYCHOTHERAPISTS_DB_DEV } from "../statics"; import { FilterType } from "src/types/Filter"; +async function getTherapistsByName( + name: string, + dbInstance: DocumentScope +) { + const psychotherapists = []; + console.log(name); + + const viewResponse = await dbInstance.view( + "therapistsDesignDoc", + "therapistsByName", + { + startkey: name, + endkey: name + "\ufff0", + include_docs: true, + } + ); + + viewResponse.rows.map((row) => { + if (row.doc) { + psychotherapists.push(row.doc); + } + }); + + return psychotherapists; +} + async function getTherapistsFromView( viewName: string, keys: any = [], @@ -201,6 +227,22 @@ export class PsychotherapistService implements PsychotherapistServiceApi { } } + if (filter.name) { + try { + let psychotherapists = await getTherapistsByName( + filter.name[0], + this.psychotherapistDb + ); + + allPsychotherapists.push(...psychotherapists); + } catch (error) { + this.logger.error(error); + throw new InternalServerError( + `getPsychotherapists: Failed to retrieve psychotherapists` + ); + } + } + const seen = new Set(); response.psychotherapists = allPsychotherapists.filter((el) => { diff --git a/src/types/Filter.ts b/src/types/Filter.ts index d725bfe..f21b068 100644 --- a/src/types/Filter.ts +++ b/src/types/Filter.ts @@ -5,9 +5,11 @@ export interface FilterType { patientgroups?: string[]; price?: string[]; legalpersonality?: string[]; + name?: string[]; } export interface FilterQueryParam { languages?: string[] | string; patientgroups?: string[] | string; + name?: string[] | string; } diff --git a/src/util/filter-util.ts b/src/util/filter-util.ts index 7059de2..18e55e2 100644 --- a/src/util/filter-util.ts +++ b/src/util/filter-util.ts @@ -8,6 +8,7 @@ export function sanitizeFilter(unSafeFilter: any): FilterType { patientgroups: "string", price: "string", legalpersonality: "string", + name: "string", }; let cleanFilter: FilterType = {}; diff --git a/web-app/src/constants/directory.js b/web-app/src/constants/directory.js index 23040b0..971f458 100644 --- a/web-app/src/constants/directory.js +++ b/web-app/src/constants/directory.js @@ -207,4 +207,8 @@ export const collapsiblesInitial = { }, ], }, + name: { + label: "Name of mental health professional or organization", + value: "", + }, }; diff --git a/web-app/src/pages/directory/components/Sidebar.js b/web-app/src/pages/directory/components/Sidebar.js index 6487930..f9f76bc 100644 --- a/web-app/src/pages/directory/components/Sidebar.js +++ b/web-app/src/pages/directory/components/Sidebar.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useCallback } from "react"; import Collapsible from "react-collapsible"; import styled from "styled-components"; @@ -16,42 +16,71 @@ const Sidebar = ({ onFilterChange }) => { if (onFilterChange) onFilterChange(collapsibles); }, [collapsibles]); + const renderCollapsibles = useCallback(() => { + return Object.keys(collapsibles).map((key, index) => { + if (collapsibles[key].options) { + return ( + + {collapsibles[key].options.map((option, index2) => { + return ( + + ); + })} + + ); + } else if (collapsibles[key].value !== undefined) { + return ( + + + + { + let collapsiblesCopy = { ...collapsibles }; + collapsiblesCopy[key].value = e.target.value; + setCollapsibles({ ...collapsiblesCopy }); + }} + /> + + + + + + + ); + } + return null; + }); + }, [collapsibles, setCollapsibles]); + return ( <> Filters {/* bunch of collapsibles */} -
- {Object.keys(collapsibles).map((key, index) => { - return ( - - {collapsibles[key].options.map((option, index2) => { - return ( - - ); - })} - - ); - })} -
+
{renderCollapsibles()}
@@ -71,6 +100,8 @@ const SearchInputContainer = styled.div` const SearchInput = styled.input` fontsize: 14px; + height: 100%; + outline: none; width: 100%; margin: 0; border: none; diff --git a/web-app/src/pages/directory/components/__snapshots__/Sidebar.spec.js.snap b/web-app/src/pages/directory/components/__snapshots__/Sidebar.spec.js.snap index 97d8f4a..f058e2e 100644 --- a/web-app/src/pages/directory/components/__snapshots__/Sidebar.spec.js.snap +++ b/web-app/src/pages/directory/components/__snapshots__/Sidebar.spec.js.snap @@ -805,6 +805,51 @@ exports[`the Sidebar component should be able to click on collapsible to show mo `; exports[`the Sidebar component should match the snapshot 1`] = ` +.c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + height: 32px; + border: 1px solid #d9d9d9; +} + +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; +} + +.c5 { + fontsize: 14px; + height: 100%; + outline: none; + width: 100%; + margin: 0; + border: none; +} + +.c6 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + width: 32px; + border-left: 1px solid #d9d9d9; +} + .c1 { background-color: inherit; width: 100%; @@ -1429,6 +1474,52 @@ exports[`the Sidebar component should match the snapshot 1`] = ` +
+ +
+
+
+
+ +
+ +
+
+
+
+
+
diff --git a/web-app/src/pages/directory/directoryPage.js b/web-app/src/pages/directory/directoryPage.js index 20d0a44..eb16b7e 100644 --- a/web-app/src/pages/directory/directoryPage.js +++ b/web-app/src/pages/directory/directoryPage.js @@ -209,9 +209,13 @@ const DirectoryPage = () => { let adaptedFilter = {}; for (let filterKey in filter) { - adaptedFilter[filterKey] = filter[filterKey].options - .filter((option) => option.selected === true) - .map((option) => option.value); + if (filter[filterKey].options) { + adaptedFilter[filterKey] = filter[filterKey].options + .filter((option) => option.selected === true) + .map((option) => option.value); + } else if (filter[filterKey].value) { + adaptedFilter[filterKey] = [filter[filterKey].value]; + } } const result = await getTherapists(adaptedFilter);