Skip to content

Commit 742f314

Browse files
committed
part 9e
1 parent 68d1d9b commit 742f314

File tree

4 files changed

+489
-904
lines changed

4 files changed

+489
-904
lines changed

src/content/9/en/part9e.md

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ lang: en
1010

1111
### Working with an existing codebase
1212

13-
When diving into an existing codebase for the first time, it is good to get an overall view of the conventions and structure of the project. You can start your research by reading the <i>README.md</i> in the root of the repository. Usually, the README contains a brief description of the application and the requirements for using it, as well as how to start it for development.
14-
If the README is not available or someone has "saved time" and left it as a stub, you can take a peek at the <i>package.json</i>.
13+
When diving into an existing codebase for the first time, it is good to get an overall view of the conventions and structure of the project. You can start your research by reading the *README.md* in the root of the repository. Usually, the README contains a brief description of the application and the requirements for using it, as well as how to start it for development.
14+
If the README is not available or someone has "saved time" and left it as a stub, you can take a peek at the *package.json*.
1515
It is always a good idea to start the application and click around to verify you have a functional development environment.
1616

1717
You can also browse the folder structure to get some insight into the application's functionality and/or the architecture used. These are not always clear, and the developers might have chosen a way to organize code that is not familiar to you. The [sample project](https://github.com/fullstack-hy2020/patientor) used in the rest of this part is organized, feature-wise. You can see what pages the application has, and some general components, e.g. modals and state. Keep in mind that the features may have different scopes. For example, modals are visible UI-level components whereas the state is comparable to business logic and keeps the data organized under the hood for the rest of the app to use.
1818

19-
TypeScript provides types for what kind of data structures, functions, components, and state to expect. You can try looking for <i>types.ts</i> or something similar to get started. VSCode is a big help and simply highlighting variables and parameters can provide quite a lot of insight. All this naturally depends on how types are used in the project.
19+
TypeScript provides types for what kind of data structures, functions, components, and state to expect. You can try looking for *types.ts* or something similar to get started. VSCode is a big help and simply highlighting variables and parameters can provide quite a lot of insight. All this naturally depends on how types are used in the project.
2020

2121
If the project has unit, integration or end-to-end tests, reading those is most likely beneficial. Test cases are your most important tool when refactoring or adding new features to the application. You want to make sure not to break any existing features when hammering around the code. TypeScript can also give you guidance with argument and return types when changing the code.
2222

@@ -30,7 +30,7 @@ Before diving into the code, let us start both the frontend and the backend.
3030

3131
If all goes well, you should see a patient listing page. It fetches a list of patients from our backend, and renders it to the screen as a simple table. There is also a button for creating new patients on the backend. As we are using mock data instead of a database, the data will not persist - closing the backend will delete all the data we have added. UI design has not been a strong point of the creators, so let's disregard the UI for now.
3232

33-
After verifying that everything works, we can start studying the code. All the interesting stuff resides in the <i>src</i> folder. For your convenience, there is already a <i>types.ts</i> file for basic types used in the app, which you will have to extend or refactor in the exercises.
33+
After verifying that everything works, we can start studying the code. All the interesting stuff resides in the *src* folder. For your convenience, there is already a *types.ts* file for basic types used in the app, which you will have to extend or refactor in the exercises.
3434

3535
In principle, we could use the same types for both backend and frontend, but usually, the frontend has different data structures and use cases for the data, which causes the types to be different.
3636
For example, the frontend has a state and may want to keep data in objects or maps whereas the backend uses an array. The frontend might also not need all the fields of a data object saved in the backend, and it may need to add some new fields to use for rendering.
@@ -139,7 +139,7 @@ const AddPatientModal = ({ modalOpen, onClose, onSubmit, error }: Props) => {
139139
}
140140
```
141141

142-
*onClose* is just a function that takes no parameters, and does not return anything, so the type is
142+
*onClose* is just a function that takes no parameters, and does not return anything, so the type is:
143143

144144
```js
145145
() => void
@@ -159,13 +159,13 @@ The return value of a *async* function is a [promise](https://developer.mozilla.
159159

160160
### Exercises 9.20-9.21
161161

162-
We will soon add a new type for our app, *Entry*, which represents a lightweight patient journal entry. It consists of a journal text, i.e. a *description*, a creation date, information regarding the specialist who created it and possible diagnosis codes. Diagnosis codes map to the ICD-10 codes returned from the <i>/api/diagnoses</i> endpoint. Our naive implementation will be that a patient has an array of entries.
162+
We will soon add a new type for our app, *Entry*, which represents a lightweight patient journal entry. It consists of a journal text, i.e. a *description*, a creation date, information regarding the specialist who created it and possible diagnosis codes. Diagnosis codes map to the ICD-10 codes returned from the */api/diagnoses* endpoint. Our naive implementation will be that a patient has an array of entries.
163163

164164
Before going into this, let us do some preparatory work.
165165

166166
#### 9.20: Patientor, step1
167167

168-
Create an endpoint <i>/api/patients/:id</i> to the backend that returns all of the patient information for one patient, including the array of patient entries that is still empty for all the patients. For the time being, expand the backend types as follows:
168+
Create an endpoint */api/patients/:id* to the backend that returns all of the patient information for one patient, including the array of patient entries that is still empty for all the patients. For the time being, expand the backend types as follows:
169169

170170
```js
171171
// eslint-disable-next-line @typescript-eslint/no-empty-interface
@@ -260,8 +260,7 @@ All the entries seem to have some fields in common, but some fields are entry-sp
260260
When looking at the *type*, we can see that there are three kinds of entries: *OccupationalHealthcare*, *Hospital* and *HealthCheck*.
261261
This indicates we need three separate types. Since they all have some fields in common, we might just want to create a base entry interface that we can extend with the different fields in each type.
262262

263-
When looking at the data, it seems that the fields *id*, *description*, *date* and *specialist* are something that can be found in each entry. On top of that, it seems that *diagnosisCodes* is only found in one *OccupationalHealthcare* and one *Hospital* type entry. Since it is not always used even in those types of entries, it is safe to assume that the field is optional. We could consider adding it to the *HealthCheck* type as well
264-
since it might just not be used in these specific entries.
263+
When looking at the data, it seems that the fields *id*, *description*, *date* and *specialist* are something that can be found in each entry. On top of that, it seems that *diagnosisCodes* is only found in one *OccupationalHealthcare* and one *Hospital* type entry. Since it is not always used, even in those types of entries, it is safe to assume that the field is optional. We could consider adding it to the *HealthCheck* type as well since it might just not be used in these specific entries.
265264

266265
So our *BaseEntry* from which each type could be extended would be the following:
267266

@@ -302,7 +301,7 @@ interface BaseEntry {
302301

303302
Now that we have the *BaseEntry* defined, we can start creating the extended entry types we will actually be using. Let's start by creating the *HealthCheckEntry* type.
304303

305-
Entries of type *HealthCheck* contain the field *HealthCheckRating*, which is an integer from 0 to 3, zero meaning *Healthy* and 3 meaning *CriticalRisk*. This is a perfect case for an enum definition.
304+
Entries of type *HealthCheck* contain the field *HealthCheckRating*, which is an integer from 0 to 3, zero meaning *Healthy* and three meaning *CriticalRisk*. This is a perfect case for an enum definition.
306305
With these specifications we could write a *HealthCheckEntry* type definition like so:
307306

308307
```js
@@ -330,7 +329,7 @@ export type Entry =
330329

331330
### Omit with unions
332331

333-
An important point concerning unions is that, when you use them with *Omit* to exclude a property, it works in a possibly unexpected way. Suppose we want to remove the *id* from each *Entry*. We could think of using
332+
An important point concerning unions is that, when you use them with *Omit* to exclude a property, it works in a possibly unexpected way. Suppose that we want to remove the *id* from each *Entry*. We could think of using
334333

335334
```js
336335
Omit<Entry, 'id'>
@@ -353,15 +352,15 @@ type EntryWithoutId = UnionOmit<Entry, 'id'>;
353352

354353
Now we are ready to put the finishing touches to the app!
355354

356-
#### 9.22: Patientor, step3
355+
#### 9.22: Patientor, step 3
357356

358-
Define the types *OccupationalHealthcareEntry* and *HospitalEntry* so that those conform with the example data. Ensure that your backend returns the entries properly when you go to an individual patient's route:
357+
Define the types *OccupationalHealthcareEntry* and *HospitalEntry* so that those conform with the new example data. Ensure that your backend returns the entries properly when you go to an individual patient's route:
359358

360-
![browser shoiwing entries json data properly for patient](../../images/9/40.png)
359+
![browser showing entries json data properly for patient](../../images/9/40.png)
361360

362361
Use types properly in the backend! For now, there is no need to do a proper validation for all the fields of the entries in the backend, it is enough e.g. to check that the field *type* has a correct value.
363362

364-
#### 9.23: Patientor, step4
363+
#### 9.23: Patientor, step 4
365364

366365
Extend a patient's page in the frontend to list the *date*, *description* and *diagnoseCodes* of the patient's entries.
367366

@@ -371,33 +370,33 @@ Your solution could look like this:
371370

372371
![browser showing list of diagnosis codes for patient](../../images/9/41.png)
373372

374-
#### 9.24: Patientor, step5
373+
#### 9.24: Patientor, step 5
375374

376-
Fetch and add diagnoses to the application state from the <i>/api/diagnoses</i> endpoint. Use the new diagnosis data to show the descriptions for patient's diagnosis codes:
375+
Fetch and add diagnoses to the application state from the */api/diagnoses* endpoint. Use the new diagnosis data to show the descriptions for patient's diagnosis codes:
377376

378377
![browser showing list of codes and their descriptions for patient ](../../images/9/42.png)
379378

380-
#### 9.25: Patientor, step6
379+
#### 9.25: Patientor, step 6
381380

382-
Extend the entry listing on the patient's page to include the Entry's details with a new component that shows the rest of the information of the patient's entries distinguishing different types from each other.
381+
Extend the entry listing on the patient's page to include the Entry's details, with a new component that shows the rest of the information of the patient's entries, distinguishing different types from each other.
383382

384383
You could use eg. [Icons](https://mui.com/components/material-icons/) or some other [Material UI](https://mui.com/) component to get appropriate visuals for your listing.
385384

386-
You should use a *switch case*-based rendering and <i>exhaustive type checking</i> so that no cases can be forgotten.
385+
You should use a *switch case*-based rendering and *exhaustive type checking* so that no cases can be forgotten.
387386

388387
Like this:
389388

390389
![vscode showing error for healthCheckEntry not being assignable to type never](../../images/9/35c.png)
391390

392-
The resulting entries in the listing <i>could</i> look something like this:
391+
The resulting entries in the listing *could* look something like this:
393392

394393
![browser showing list of entries and their details in a nicer format](../../images/9/36x.png)
395394

396-
#### 9.26: Patientor, step7
395+
#### 9.26: Patientor, step 7
397396

398397
We have established that patients can have different kinds of entries. We don't yet have any way of adding entries to patients in our app, so, at the moment, it is pretty useless as an electronic medical record.
399398

400-
Your next task is to add endpoint <i>/api/patients/:id/entries</i> to your backend, through which you can POST an entry for a patient.
399+
Your next task is to add endpoint */api/patients/:id/entries* to your backend, through which you can POST an entry for a patient.
401400

402401
Remember that we have different kinds of entries in our app, so our backend should support all those types and check that at least all required fields are given for each type.
403402

@@ -416,11 +415,11 @@ const parseDiagnosisCodes = (object: unknown): Array<Diagnosis['code']> => {
416415
};
417416
```
418417

419-
#### 9.27: Patientor, step8
418+
#### 9.27: Patientor, step 8
420419

421420
Now that our backend supports adding entries, we want to add the corresponding functionality to the frontend. In this exercise, you should add a form for adding an entry to a patient. An intuitive place for accessing the form would be on a patient's page.
422421

423-
In this exercise, it is enough to **support <i>one</i> entry type**. All the fields in the form can be just plain text inputs, so it is up to user to enter valid values.
422+
In this exercise, it is enough to **support *one* entry type**. All the fields in the form can be just plain text inputs, so it is up to user to enter valid values.
424423

425424
Upon a successful submit, the new entry should be added to the correct patient and the patient's entries on the patient page should be updated to contain the new entry.
426425

@@ -432,11 +431,11 @@ If user enters invalid values to the form and backend rejects the addition, show
432431

433432
![browser showing healthCheckRating incorrect 15 error](../../images/9/75new.png)
434433

435-
#### 9.28: Patientor, step9
434+
#### 9.28: Patientor, step 9
436435

437-
Extend your solution so that it supports <i>all the entry types</i>
436+
Extend your solution so that it supports *all the entry types*
438437

439-
#### 9.29: Patientor, step10
438+
#### 9.29: Patientor, step 10
440439

441440
Improve the entry creation forms so that it makes hard to enter incorrect dates, diagnosis codes and health rating.
442441

src/content/9/es/part9d.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ Entonces, nuestro código es esencialmente tan seguro como seria si utilizáramo
862862
863863
Ya que los tipos de TypeScript ni siquiera existen durante el tiempo de ejecución, nuestro código no nos ofrece "seguridad" en situaciones en las que el body de la solicitud contenga datos con el formato erróneo.
864864
865-
Darle una variable de tipo a *axios.get* podría estar bien si estamos *absolutamente seguros* de que el backend se comporta correctamente y siempre devuelve los datos en el formato correcto. Si queremos construir un sistema robusto deberíamos prepararnos para sorpresas y procesar los datos de la respuesta en el frontend similarmente a como lo hicimos [en la sección previa](/es/part9/escribiendo_una_aplicacion_express#solicitudes-de-revision) para las solicitudes al backend.
865+
Darle una variable de tipo a *axios.get* podría estar bien si estamos *absolutamente seguros* de que el backend se comporta correctamente y siempre devuelve los datos en el formato correcto. Si queremos construir un sistema robusto deberíamos prepararnos para sorpresas y procesar los datos de la respuesta en el frontend similarmente a como lo hicimos [en la sección previa](/es/part9/tipando_una_aplicacion_express#solicitudes-de-revision) para las solicitudes al backend.
866866
867867
Concluyamos ahora nuestra aplicación implementando la nueva adición de notas:
868868
@@ -1002,7 +1002,7 @@ La documentación de TypeScript [recomienda el uso de interfaces](https://www.ty
10021002
10031003
### Ejercicios 9.16-9.19
10041004
1005-
Ahora construyamos un frontend para la aplicación de diarios de vuelo de Ilari que fue desarrollada [en la sección anterior](/es/part9/escribiendo_una_aplicacion_express). El código fuente del backend puede encontrarse en [este repositorio de GitHub](https://github.com/fullstack-hy2020/flight-diary).
1005+
Ahora construyamos un frontend para la aplicación de diarios de vuelo de Ilari que fue desarrollada [en la sección anterior](/es/part9/tipando_una_aplicacion_express). El código fuente del backend puede encontrarse en [este repositorio de GitHub](https://github.com/fullstack-hy2020/flight-diary).
10061006
10071007
#### Ejercicio 9.16
10081008

0 commit comments

Comments
 (0)