Skip to content
Snippets Groups Projects
Commit e8e61c10 authored by Mateusz Bolewski's avatar Mateusz Bolewski
Browse files

Merge branch 'feature/search-drugs-details' into 'development'

Feature/search drugs details

See merge request !51
parents 3185502d 0ebba14e
No related branches found
No related tags found
2 merge requests!223reset the pin numbers before search results are fetch (so the results will be...,!51Feature/search drugs details
Pipeline #81273 passed
......@@ -33,7 +33,7 @@ describe('DrugsAccordion - component', () => {
renderComponent({
drugs: { data: drugsFixture, loading: 'succeeded', error: { name: '', message: '' } },
});
expect(screen.getByText('Drugs (2)')).toBeInTheDocument();
expect(screen.getByText('Drugs (4)')).toBeInTheDocument();
});
it('should display loading indicator while waiting for drug search response', () => {
renderComponent({
......
/* eslint-disable no-magic-numbers */
import { drugsFixture } from '@/models/fixtures/drugFixtures';
import { StoreType } from '@/redux/store';
import {
InitialStoreState,
getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { render, screen } from '@testing-library/react';
import { AccordionsDetails } from './AccordionsDetails.component';
const PINS_LIST = drugsFixture.map(drug => ({
id: drug.id,
name: drug.name,
data: drug,
}));
const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);
return (
render(
<Wrapper>
<AccordionsDetails pinsList={PINS_LIST} />
</Wrapper>,
),
{
store,
}
);
};
describe('AccordionsDetails - component', () => {
it('should display name of drug', () => {
renderComponent();
const drugName = drugsFixture[0].name;
expect(screen.getByText(drugName, { exact: false })).toBeInTheDocument();
});
it('should display description of drug', () => {
renderComponent();
const drugDescription = drugsFixture[0].description;
expect(screen.getByText(drugDescription, { exact: false })).toBeInTheDocument();
});
it('should display synonyms of drug', () => {
renderComponent();
const firstDrugSynonym = drugsFixture[0].synonyms[0];
const secondDrugSynonym = drugsFixture[0].synonyms[1];
expect(screen.getByText(firstDrugSynonym, { exact: false })).toBeInTheDocument();
expect(screen.getByText(secondDrugSynonym, { exact: false })).toBeInTheDocument();
});
it('should display additional info about drug', () => {
renderComponent();
const drugAdditionalInfo = drugsFixture[0].bloodBrainBarrier;
expect(screen.getByText(drugAdditionalInfo, { exact: false })).toBeInTheDocument();
});
});
import {
Accordion,
AccordionItem,
AccordionItemButton,
AccordionItemHeading,
AccordionItemPanel,
} from '@/shared/Accordion';
import { PinItem } from '../PinsList/PinsList.types';
import {
getAdditionalInfo,
getEntityDescriptions,
getEntityNames,
getEntitySynonyms,
} from './AccordionsDetails.utils';
interface AccordionsDetailsProps {
pinsList: PinItem[];
}
export const AccordionsDetails = ({ pinsList }: AccordionsDetailsProps): JSX.Element => {
return (
<>
<Accordion allowZeroExpanded className="px-6">
<AccordionItem>
<AccordionItemHeading>
<AccordionItemButton>Drug</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>{getEntityNames(pinsList)}</AccordionItemPanel>
</AccordionItem>
<AccordionItem>
<AccordionItemHeading>
<AccordionItemButton>Description</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>{getEntityDescriptions(pinsList)}</AccordionItemPanel>
</AccordionItem>
<AccordionItem>
<AccordionItemHeading>
<AccordionItemButton>Synonyms</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>{getEntitySynonyms(pinsList)}</AccordionItemPanel>
</AccordionItem>
</Accordion>
<div className="flex justify-between px-6 py-4 text-sm font-bold">
<div>Blood brain barrier</div>
<div>{getAdditionalInfo(pinsList)}</div>
</div>
</>
);
};
import { PinItem } from '../PinsList/PinsList.types';
export const getEntityNames = (pinsList: PinItem[]): string => {
let name = '';
pinsList.forEach(element => {
name += element.data.name;
});
return name;
};
export const getEntityDescriptions = (pinsList: PinItem[]): string => {
let description = '';
pinsList.forEach(element => {
if ('description' in element.data) {
description += element.data.description;
}
});
return description;
};
export const getEntitySynonyms = (pinsList: PinItem[]): string => {
let synonyms = '';
pinsList.forEach(element => {
if ('synonyms' in element.data) {
synonyms += element.data.synonyms.join(', ');
}
});
return synonyms;
};
export const getAdditionalInfo = (pinsList: PinItem[]): string => {
let additionalDetails = '';
pinsList.forEach(element => {
if ('bloodBrainBarrier' in element.data) {
additionalDetails += element.data.bloodBrainBarrier;
}
});
return additionalDetails;
};
import { assertNever } from '@/utils/assertNever';
import { AccordionsDetails } from '../AccordionsDetails/AccordionsDetails.component';
import { PinItem, PinType } from './PinsList.types';
import { MirnaPinsListItem } from './PinsListItem';
......@@ -9,18 +10,29 @@ interface PinsListProps {
export const PinsList = ({ pinsList, type }: PinsListProps): JSX.Element => {
switch (type) {
case 'drugs':
return (
<div className="h-[calc(100vh-198px)] overflow-auto">
<AccordionsDetails pinsList={pinsList} />
<ul className="px-6 py-2">
{pinsList.map(result => {
return result.data.targets.map(pin => (
<MirnaPinsListItem key={pin.name} name={pin.name} type={type} pin={pin} />
));
})}
</ul>
</div>
);
case 'bioEntity':
return <div />;
case 'chemicals':
return <div />;
case 'drugs':
return <div />;
case 'mirna':
return (
<ul className="h-[calc(100vh-198px)] overflow-auto px-6 py-2">
{pinsList.map(result => {
return result.data.targets.map(pin => (
<MirnaPinsListItem key={pin.name} name={pin.name} pin={pin} />
<MirnaPinsListItem key={pin.name} name={pin.name} type={type} pin={pin} />
));
})}
</ul>
......
......@@ -2,19 +2,22 @@ import { twMerge } from 'tailwind-merge';
import { Icon } from '@/shared/Icon';
import { MirnaItems } from '@/types/models';
import { getPinColor } from './PinsListItem.component.utils';
import { PinType } from '../PinsList.types';
interface MirnaPinsListItemProps {
name: string;
type: PinType;
pin: MirnaItems;
}
export const MirnaPinsListItem = ({ name, pin }: MirnaPinsListItemProps): JSX.Element => {
export const MirnaPinsListItem = ({ name, type, pin }: MirnaPinsListItemProps): JSX.Element => {
return (
<div className="mb-4 flex w-full flex-col gap-2 rounded-lg border-[1px] border-solid border-greyscale-500 p-4">
<div className="flex w-full flex-row gap-2">
<Icon name="pin" className={twMerge('mr-2 shrink-0', getPinColor('mirna'))} />
<p className="min-w-fit">Full name: </p>
<p className="w-full font-bold">{name}</p>
<div className="mb-4 flex w-full flex-col gap-3 rounded-lg border-[1px] border-solid border-greyscale-500 p-4">
<div className="flex w-full flex-row items-center gap-2">
<Icon name="pin" className={twMerge('mr-2 shrink-0', getPinColor(type))} />
<p>
Full name: <span className="w-full font-bold">{name}</span>
</p>
</div>
<ul className="leading-6">
<div className="font-bold">Elements:</div>
......
......@@ -5,6 +5,16 @@ import { createSelector } from '@reduxjs/toolkit';
export const drugsSelector = createSelector(rootSelector, state => state.drugs);
export const loadingDrugsStatusSelector = createSelector(drugsSelector, state => state.loading);
export const numberOfDrugsSelector = createSelector(drugsSelector, state =>
state.data ? state.data.length : SIZE_OF_EMPTY_ARRAY,
);
export const numberOfDrugsSelector = createSelector(drugsSelector, state => {
if (!state.data) {
return SIZE_OF_EMPTY_ARRAY;
}
let numberOfDrugs = 0;
state.data.forEach(element => {
numberOfDrugs += element.targets.length;
});
return numberOfDrugs;
});
......@@ -847,9 +847,9 @@
"resolved" "https://registry.npmjs.org/@next/font/-/font-13.5.4.tgz"
"version" "13.5.4"
"@next/swc-darwin-arm64@13.4.19":
"integrity" "sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ=="
"resolved" "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.19.tgz"
"@next/swc-darwin-x64@13.4.19":
"integrity" "sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw=="
"resolved" "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.19.tgz"
"version" "13.4.19"
"@nodelib/fs.scandir@2.1.5":
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment