github.com/lauslim12/expert-systems@v0.0.0-20221115131159-018513aad29c/web/src/components/Modal/ResultModal.tsx (about)

     1  import {
     2    Alert,
     3    AlertIcon,
     4    Button,
     5    ButtonGroup,
     6    chakra,
     7    Link,
     8    List,
     9    ListIcon,
    10    ListItem,
    11    Modal,
    12    ModalBody,
    13    ModalCloseButton,
    14    ModalContent,
    15    ModalFooter,
    16    ModalHeader,
    17    ModalOverlay,
    18    Text,
    19    Textarea,
    20    VStack,
    21  } from '@chakra-ui/react';
    22  import { memo, useState } from 'react';
    23  import { useTranslation } from 'react-i18next';
    24  import {
    25    AiFillInfoCircle,
    26    AiOutlineClose,
    27    AiOutlineCode,
    28  } from 'react-icons/ai';
    29  
    30  import type Response from '../../types/Response';
    31  
    32  /**
    33   * Accepts ChakraUI's modal props, plus the response from the API.
    34   */
    35  type Props = {
    36    isOpen: boolean;
    37    onClose: () => void;
    38    results: Response;
    39  };
    40  
    41  /**
    42   * This modal will render the results of the inference.
    43   *
    44   * @param param - ChakraUI's modal props, and the API response
    45   * @returns React Functional Component
    46   */
    47  const ResultModal = ({ isOpen, onClose, results }: Props) => {
    48    const [showRawData, setShowRawData] = useState(false);
    49    const { t } = useTranslation();
    50  
    51    /**
    52     * Renders the suggestion of what the user should do based on their probability rate.
    53     *
    54     * @param probability - The probability of having TB
    55     * @returns JSX Element
    56     */
    57    const renderSuggestion = (probability: number) => {
    58      if (probability <= 30) {
    59        return <Text>{t('inference.suggestionOkay')}</Text>;
    60      }
    61  
    62      if (probability > 30 && probability < 70) {
    63        return <Text>{t('inference.suggestionVisit')}</Text>;
    64      }
    65  
    66      return <Text>{t('inference.suggestionDangerous')}</Text>;
    67    };
    68  
    69    return (
    70      <Modal
    71        isOpen={isOpen}
    72        onClose={onClose}
    73        size="5xl"
    74        motionPreset="slideInBottom"
    75        closeOnEsc={false}
    76        closeOnOverlayClick={false}
    77      >
    78        <ModalOverlay />
    79  
    80        <ModalContent>
    81          <ModalHeader>{t('inference.title')}</ModalHeader>
    82          <ModalCloseButton />
    83  
    84          <ModalBody>
    85            <VStack as="article" align="stretch">
    86              <Alert as="section" status="success" variant="solid">
    87                <AlertIcon />
    88                {t('inference.alert')}
    89              </Alert>
    90  
    91              <VStack as="section" align="start" spacing={4}>
    92                {results.data && (
    93                  <>
    94                    <VStack align="start">
    95                      <Text fontSize="lg" fontWeight="bold">
    96                        {t('inference.verdict')}
    97                      </Text>
    98  
    99                      <Text
   100                        color={
   101                          results.data.verdict === true
   102                            ? 'orange.400'
   103                            : 'twitter.400'
   104                        }
   105                        fontWeight="bold"
   106                      >
   107                        {results.data.verdict === true
   108                          ? t('inference.verdictTB')
   109                          : t('inference.verdictNoTB')}
   110                      </Text>
   111  
   112                      <Text>{t('inference.verdictCalculation')}</Text>
   113                    </VStack>
   114  
   115                    <VStack align="start">
   116                      <Text fontSize="lg" fontWeight="bold">
   117                        {t('inference.probability')}
   118                      </Text>
   119  
   120                      <Text fontWeight="bold" color="pink.400">
   121                        {t('inference.probabilityResult', {
   122                          probability: (results.data.probability * 100).toFixed(
   123                            2
   124                          ),
   125                        })}
   126                      </Text>
   127  
   128                      <Text>{t('inference.probabilityCalculation')}</Text>
   129                    </VStack>
   130  
   131                    <VStack align="start">
   132                      <Text fontSize="lg" fontWeight="bold">
   133                        {t('inference.suggestion')}
   134                      </Text>
   135  
   136                      {renderSuggestion(
   137                        parseFloat((results.data.probability * 100).toFixed(2))
   138                      )}
   139                    </VStack>
   140  
   141                    <VStack align="start">
   142                      <Text fontSize="lg" fontWeight="bold">
   143                        {t('inference.information')}
   144                      </Text>
   145  
   146                      <Text>{results.data.disease.description}</Text>
   147                    </VStack>
   148  
   149                    <VStack align="start">
   150                      <Text fontSize="lg" fontWeight="bold">
   151                        {t('inference.prevention')}
   152                      </Text>
   153  
   154                      <Text>{results.data.disease.prevention}</Text>
   155                    </VStack>
   156  
   157                    <VStack align="start">
   158                      <Text fontSize="lg" fontWeight="bold">
   159                        {t('inference.treatment')}
   160                      </Text>
   161  
   162                      <Text>{results.data.disease.treatment}</Text>
   163                    </VStack>
   164  
   165                    <VStack align="start">
   166                      <Text fontSize="lg" fontWeight="bold">
   167                        {t('inference.sources')}
   168                      </Text>
   169  
   170                      <Text>{t('inference.sourcesBeginning')}</Text>
   171  
   172                      <List>
   173                        {results.data.disease.source.map((source) => (
   174                          <ListItem key={source.name}>
   175                            <ListIcon as={AiFillInfoCircle} color="green.500" />
   176  
   177                            <Link
   178                              color="twitter.500"
   179                              href={source.link}
   180                              isExternal
   181                            >
   182                              {source.name}
   183                            </Link>
   184                          </ListItem>
   185                        ))}
   186                      </List>
   187                    </VStack>
   188  
   189                    {showRawData && (
   190                      <VStack align="start" w="full">
   191                        <Text fontSize="lg" fontWeight="bold">
   192                          {t('inference.json')}
   193                        </Text>
   194  
   195                        <Text>{t('inference.jsonBeginning')}</Text>
   196  
   197                        <chakra.code w="full">
   198                          <Textarea
   199                            value={JSON.stringify(results, null, 2)}
   200                            w="full"
   201                            h="50vh"
   202                            readOnly
   203                          />
   204                        </chakra.code>
   205                      </VStack>
   206                    )}
   207                  </>
   208                )}
   209              </VStack>
   210            </VStack>
   211          </ModalBody>
   212  
   213          <ModalFooter>
   214            <ButtonGroup>
   215              <Button
   216                colorScheme="twitter"
   217                leftIcon={<AiOutlineCode />}
   218                onClick={() => setShowRawData(!showRawData)}
   219              >
   220                {showRawData === true
   221                  ? t('inference.hideCode')
   222                  : t('inference.showCode')}
   223              </Button>
   224  
   225              <Button
   226                colorScheme="red"
   227                leftIcon={<AiOutlineClose />}
   228                onClick={onClose}
   229              >
   230                {t('inference.close')}
   231              </Button>
   232            </ButtonGroup>
   233          </ModalFooter>
   234        </ModalContent>
   235      </Modal>
   236    );
   237  };
   238  
   239  export default memo(ResultModal);