github.com/lauslim12/expert-systems@v0.0.0-20221115131159-018513aad29c/web/src/components/Tuberculosis.tsx (about) 1 import { Button, Text, useToast, VStack } from '@chakra-ui/react'; 2 import { lazy, memo, Suspense, useState } from 'react'; 3 import { useTranslation } from 'react-i18next'; 4 5 import type Request from '../types/Request'; 6 import type Response from '../types/Response'; 7 import type { StateCertaintyWeight } from '../types/UserCertaintyWeight'; 8 import request from '../utils/request'; 9 import FailedToast from './FailedToast'; 10 import AnswerInput from './Input/AnswerInput'; 11 12 /** 13 * Lazy-load modal, as it is not displayed right away. 14 */ 15 const ResultModal = lazy(() => import('../components/Modal/ResultModal')); 16 17 /** 18 * Tuberculosis component to infer, render, and handle user inputs about this disease. 19 * 20 * @returns React Functional Component 21 */ 22 const Tuberculosis = () => { 23 const [isLoading, setIsLoading] = useState(false); 24 const [openResult, setOpenResult] = useState(false); 25 const [result, setResult] = useState({} as Response); 26 const [fever, setFever] = useState(null as StateCertaintyWeight); 27 const [coughBlood, setCoughBlood] = useState(null as StateCertaintyWeight); 28 const [spBloody, setSpBloody] = useState(null as StateCertaintyWeight); 29 const [nightSweat, setNightSweat] = useState(null as StateCertaintyWeight); 30 const [chestPain, setChestPain] = useState(null as StateCertaintyWeight); 31 const [backPain, setBackPain] = useState(null as StateCertaintyWeight); 32 const [shortBreath, setShortBreath] = useState(null as StateCertaintyWeight); 33 const [weightLoss, setWeightLoss] = useState(null as StateCertaintyWeight); 34 const [bodyTired, setBodyTired] = useState(null as StateCertaintyWeight); 35 const [lumps, setLumps] = useState(null as StateCertaintyWeight); 36 const [coughing, setCoughing] = useState(null as StateCertaintyWeight); 37 const [swollen, setSwollen] = useState(null as StateCertaintyWeight); 38 const [lossApetite, setLossApetite] = useState(null as StateCertaintyWeight); 39 const toast = useToast(); 40 const { t, i18n } = useTranslation(); 41 42 const submitResult = () => { 43 // Not '!' as 0 equals false as well. We need that literal 0 value. 44 if ( 45 fever === null || 46 coughBlood === null || 47 spBloody === null || 48 nightSweat === null || 49 chestPain === null || 50 backPain === null || 51 shortBreath === null || 52 weightLoss === null || 53 bodyTired === null || 54 lumps === null || 55 coughing === null || 56 swollen === null || 57 lossApetite === null 58 ) { 59 FailedToast(toast, t('general.notComplete')); 60 return; 61 } 62 63 const requestBody: Request = { 64 diseaseId: 'D01', 65 locale: i18n.language as 'en' | 'id', 66 symptoms: [ 67 { 68 symptomId: 'S1', 69 weight: fever, 70 }, 71 { 72 symptomId: 'S2', 73 weight: coughBlood, 74 }, 75 { 76 symptomId: 'S3', 77 weight: spBloody, 78 }, 79 { 80 symptomId: 'S4', 81 weight: nightSweat, 82 }, 83 { 84 symptomId: 'S5', 85 weight: chestPain, 86 }, 87 { 88 symptomId: 'S6', 89 weight: backPain, 90 }, 91 { 92 symptomId: 'S7', 93 weight: shortBreath, 94 }, 95 { 96 symptomId: 'S8', 97 weight: weightLoss, 98 }, 99 { 100 symptomId: 'S9', 101 weight: bodyTired, 102 }, 103 { 104 symptomId: 'S10', 105 weight: lumps, 106 }, 107 { 108 symptomId: 'S11', 109 weight: coughBlood, 110 }, 111 { 112 symptomId: 'S12', 113 weight: swollen, 114 }, 115 { 116 symptomId: 'S13', 117 weight: lossApetite, 118 }, 119 ], 120 }; 121 122 setIsLoading(true); 123 request('/api/v1', requestBody, 'POST') 124 .then((data: Response) => setResult(data)) 125 .then(() => setOpenResult(true)) 126 .catch((err) => FailedToast(toast, err.message)) 127 .finally(() => setIsLoading(false)); 128 }; 129 130 return ( 131 <> 132 <Suspense fallback={null}> 133 <ResultModal 134 isOpen={openResult} 135 onClose={() => setOpenResult(false)} 136 results={result} 137 /> 138 </Suspense> 139 140 <VStack as="form" w={['full', '70vw']} spacing={5}> 141 <AnswerInput 142 state={fever} 143 setState={setFever} 144 title={t('tbSymptoms.symptomOne')} 145 /> 146 147 <AnswerInput 148 state={coughBlood} 149 setState={setCoughBlood} 150 title={t('tbSymptoms.symptomTwo')} 151 /> 152 153 <AnswerInput 154 state={spBloody} 155 setState={setSpBloody} 156 title={t('tbSymptoms.symptomThree')} 157 /> 158 159 <AnswerInput 160 state={nightSweat} 161 setState={setNightSweat} 162 title={t('tbSymptoms.symptomFour')} 163 /> 164 165 <AnswerInput 166 state={chestPain} 167 setState={setChestPain} 168 title={t('tbSymptoms.symptomFive')} 169 /> 170 171 <AnswerInput 172 state={backPain} 173 setState={setBackPain} 174 title={t('tbSymptoms.symptomSix')} 175 /> 176 177 <AnswerInput 178 state={shortBreath} 179 setState={setShortBreath} 180 title={t('tbSymptoms.symptomSeven')} 181 /> 182 183 <AnswerInput 184 state={weightLoss} 185 setState={setWeightLoss} 186 title={t('tbSymptoms.symptomEight')} 187 /> 188 189 <AnswerInput 190 state={bodyTired} 191 setState={setBodyTired} 192 title={t('tbSymptoms.symptomNine')} 193 /> 194 195 <AnswerInput 196 state={lumps} 197 setState={setLumps} 198 title={t('tbSymptoms.symptomTen')} 199 /> 200 201 <AnswerInput 202 state={coughing} 203 setState={setCoughing} 204 title={t('tbSymptoms.symptomEleven')} 205 /> 206 207 <AnswerInput 208 state={swollen} 209 setState={setSwollen} 210 title={t('tbSymptoms.symptomTwelve')} 211 /> 212 213 <AnswerInput 214 state={lossApetite} 215 setState={setLossApetite} 216 title={t('tbSymptoms.symptomThirteen')} 217 /> 218 219 <VStack w="full" align="start"> 220 <Text fontWeight="bold">{t('general.analyze')}</Text> 221 222 <Button 223 colorScheme="pink" 224 w="full" 225 variant="solid" 226 onClick={submitResult} 227 isLoading={isLoading} 228 > 229 {t('general.results')} 230 </Button> 231 </VStack> 232 </VStack> 233 </> 234 ); 235 }; 236 237 export default memo(Tuberculosis);