You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/content/9/en/part9e.md
+27-28Lines changed: 27 additions & 28 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,13 +10,13 @@ lang: en
10
10
11
11
### Working with an existing codebase
12
12
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*.
15
15
It is always a good idea to start the application and click around to verify you have a functional development environment.
16
16
17
17
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.
18
18
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.
20
20
21
21
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.
22
22
@@ -30,7 +30,7 @@ Before diving into the code, let us start both the frontend and the backend.
30
30
31
31
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.
32
32
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.
34
34
35
35
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.
36
36
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.
*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:
143
143
144
144
```js
145
145
() =>void
@@ -159,13 +159,13 @@ The return value of a *async* function is a [promise](https://developer.mozilla.
159
159
160
160
### Exercises 9.20-9.21
161
161
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.
163
163
164
164
Before going into this, let us do some preparatory work.
165
165
166
166
#### 9.20: Patientor, step1
167
167
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:
@@ -260,8 +260,7 @@ All the entries seem to have some fields in common, but some fields are entry-sp
260
260
When looking at the *type*, we can see that there are three kinds of entries: *OccupationalHealthcare*, *Hospital* and *HealthCheck*.
261
261
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.
262
262
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.
265
264
266
265
So our *BaseEntry* from which each type could be extended would be the following:
267
266
@@ -302,7 +301,7 @@ interface BaseEntry {
302
301
303
302
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.
304
303
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.
306
305
With these specifications we could write a *HealthCheckEntry* type definition like so:
307
306
308
307
```js
@@ -330,7 +329,7 @@ export type Entry =
330
329
331
330
### Omit with unions
332
331
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
334
333
335
334
```js
336
335
Omit<Entry, 'id'>
@@ -353,15 +352,15 @@ type EntryWithoutId = UnionOmit<Entry, 'id'>;
353
352
354
353
Now we are ready to put the finishing touches to the app!
355
354
356
-
#### 9.22: Patientor, step3
355
+
#### 9.22: Patientor, step 3
357
356
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:
359
358
360
-

359
+

361
360
362
361
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.
363
362
364
-
#### 9.23: Patientor, step4
363
+
#### 9.23: Patientor, step 4
365
364
366
365
Extend a patient's page in the frontend to list the *date*, *description* and *diagnoseCodes* of the patient's entries.
367
366
@@ -371,33 +370,33 @@ Your solution could look like this:
371
370
372
371

373
372
374
-
#### 9.24: Patientor, step5
373
+
#### 9.24: Patientor, step 5
375
374
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:
377
376
378
377

379
378
380
-
#### 9.25: Patientor, step6
379
+
#### 9.25: Patientor, step 6
381
380
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.
383
382
384
383
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.
385
384
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.
387
386
388
387
Like this:
389
388
390
389

391
390
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:
393
392
394
393

395
394
396
-
#### 9.26: Patientor, step7
395
+
#### 9.26: Patientor, step 7
397
396
398
397
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.
399
398
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.
401
400
402
401
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.
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.
422
421
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.
424
423
425
424
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.
426
425
@@ -432,11 +431,11 @@ If user enters invalid values to the form and backend rejects the addition, show
Copy file name to clipboardExpand all lines: src/content/9/es/part9d.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -862,7 +862,7 @@ Entonces, nuestro código es esencialmente tan seguro como seria si utilizáramo
862
862
863
863
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.
864
864
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.
866
866
867
867
Concluyamos ahora nuestra aplicación implementando la nueva adición de notas:
868
868
@@ -1002,7 +1002,7 @@ La documentación de TypeScript [recomienda el uso de interfaces](https://www.ty
1002
1002
1003
1003
### Ejercicios 9.16-9.19
1004
1004
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).
0 commit comments