` è vuoto, il che significa che non verrà visualizzato nulla sullo schermo fino a quando non verrà aggiunto del contenuto. Occorre anche assegnarli un `ID` in modo da poterlo recuperare facilmente con JavaScript.
+
+Tornare al file `app.js` e creare una nuova funzione di supporto `updateElement`:
+
+```js
+function updateElement(id, text) {
+ const element = document.getElementById(id);
+ element.textContent = text;
+}
+```
+
+Questo è abbastanza semplice: dato un *ID* di un elemento e un *testo*, si aggiornerà il contenuto del testo dell'elemento DOM con l'`id` corrispondente. Si usa questo metodo al posto del precedente messaggio di errore nella funzione `login` :
+
+```js
+if (data.error) {
+ return updateElement('loginError', data.error);
+}
+```
+
+Ora se si prova ad accedere con un account non valido, si dovrebbe vedere qualcosa del genere:
+
+![Videata che mostra il messaggio di errore visualizzato durante l'accesso](../images/login-error.png)
+
+Ora si ha un testo di errore che viene visualizzato, ma se si prova con un lettore di schermo si noterà che non viene annunciato nulla. Affinché il testo che viene aggiunto dinamicamente a una pagina venga annunciato dai lettori di schermo, sarà necessario utilizzare qualcosa chiamato [Live Region](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Live_Regions). Qui verrà utilizzato un tipo specifico di live region chiamato alert:
+
+```html
+
+```
+
+Implementare lo stesso comportamento per gli errori della funzione `register` (non dimenticare di aggiornare l'HTML).
+
+## Visualizzare le informazioni sulla dashboard
+
+Utilizzando le stesse tecniche appena viste, ci si occuperà anche di visualizzare le informazioni dell'account nella pagina del cruscotto.
+
+Ecco come appare un oggetto account ricevuto dal server:
+
+```json
+{
+ "user": "test",
+ "currency": "$",
+ "description": "Test account",
+ "balance": 75,
+ "transactions": [
+ { "id": "1", "date": "2020-10-01", "object": "Pocket money", "amount": 50 },
+ { "id": "2", "date": "2020-10-03", "object": "Book", "amount": -10 },
+ { "id": "3", "date": "2020-10-04", "object": "Sandwich", "amount": -5 }
+ ],
+}
+```
+
+> Nota: per semplificare, si può utilizzare l'account `test` preesistente già popolato di dati.
+
+### Attività
+
+Iniziare sostituendo la sezione "Balance" (saldo) nell'HTML per aggiungere elementi segnaposto:
+
+```html
+
+```
+
+Si aggiungerà anche una nuova sezione appena sotto per visualizzare la descrizione dell'account:
+
+```html
+
+```
+
+✅ Poiché la descrizione del'account funge da titolo per il contenuto sottostante, viene contrassegnata semanticamente come intestazione (heading). Scoprire di più su come [la struttura delle intestazioni](https://www.nomensa.com/blog/2017/how-structure-headings-web-accessibility) è importante per l'accessibilità ed esaminare la pagina per determinare cos'altro potrebbe essere un'intestazione.
+
+Successivamente, verrà creata una nuova funzione in `app.js` per riempire il segnaposto:
+
+```js
+function updateDashboard() {
+ if (!account) {
+ return navigate('/login');
+ }
+
+ updateElement('description', account.description);
+ updateElement('balance', account.balance.toFixed(2));
+ updateElement('currency', account.currency);
+}
+```
+
+Innanzitutto, controllare di avere i dati dell'account necessari prima di andare oltre. Quindi si usa la funzione `updateElement()` creata in precedenza per aggiornare l'HTML.
+
+> Per rendere la visualizzazione del saldo più bella, si usa il metodo [`toFixed(2)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed) per forzare la visualizzazione del valore con 2 cifre per la parte decimale.
+
+Ora occorre chiamare la funzione `updateDashboard()` ogni volta che viene caricato il cruscotto. Se si è già terminato il [compito della lezione 1](../../1-template-route/translations/assignment.it.md) , questo dovrebbe essere immediato, altrimenti si può utilizzare la seguente implementazione.
+
+Aggiungere questo codice alla fine della funzione `updateRoute()`:
+
+```js
+if (typeof route.init === 'function') {
+ route.init();
+}
+```
+
+Aggiornare la definizione delle rotte con:
+
+```js
+const routes = {
+ '/login': { templateId: 'login' },
+ '/dashboard': { templateId: 'dashboard', init: updateDashboard }
+};
+```
+
+Con questa modifica, ogni volta che viene visualizzata la pagina del cruscotto viene chiamata la funzione `updateDashboard()`. Dopo un accesso, si dovrebbe essere in grado di vedere il saldo del conto, la valuta e la descrizione.
+
+## Creare righe di tabelle dinamicamente con modelli HTML
+
+Nella [prima lezione](../../1-template-route/translations/README.it.md) sono stati utilizzati modelli HTML insieme al metodo [`appendChild()`](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild) per implementare la navigazione nell'app. I modelli possono anche essere più piccoli e utilizzati per popolare dinamicamente parti ripetitive di una pagina.
+
+Verrà usato un approccio simile per visualizzare l'elenco delle transazioni nella tabella HTML.
+
+### Attività
+
+Aggiungere un nuovo modello nell'elemento HTML ``:
+
+```html
+
+
+ |
+ |
+ |
+
+
+```
+
+Questo modello rappresenta una singola riga di tabella, con le 3 colonne che si vuole popolare: *data*, *oggetto* e *importo* di una transazione.
+
+Aggiungere quindi la proprietà `id` all'elemento `
` della tabella all'interno del modello del cruscotto per semplificare la ricerca dell'elemento utilizzando JavaScript:
+
+```html
+
+```
+
+L'HTML è pronto, ora si passa al codice JavaScript e si crea una nuova funzione `createTransactionRow`:
+
+```js
+function createTransactionRow(transaction) {
+ const template = document.getElementById('transaction');
+ const transactionRow = template.content.cloneNode(true);
+ const tr = transactionRow.querySelector('tr');
+ tr.children[0].textContent = transaction.date;
+ tr.children[1].textContent = transaction.object;
+ tr.children[2].textContent = transaction.amount.toFixed(2);
+ return transactionRow;
+}
+```
+
+Questa funzione fa esattamente ciò che implica il suo nome: utilizzando il modello creato in precedenza, crea una nuova riga di tabella e riempie il suo contenuto utilizzando i dati della transazione. Verrà usata nella funzione `updateDashboard()` per popolare la tabella:
+
+```js
+const transactionsRows = document.createDocumentFragment();
+for (const transaction of account.transactions) {
+ const transactionRow = createTransactionRow(transaction);
+ transactionsRows.appendChild(transactionRow);
+}
+updateElement('transactions', transactionsRows);
+```
+
+Qui si utilizza il metodo [`document.createDocumentFragment()`](https://developer.mozilla.org/en-US/docs/Web/API/Document/createDocumentFragment) che crea un nuovo frammento DOM su cui si può lavorare, prima di collegarlo finalmente alla tabella HTML.
+
+C'è ancora un'altra cosa da fare prima che questo codice possa funzionare, poiché la funzione `updateElement()` attualmente supporta solo contenuto di testo. Occorre cambiare un poco il suo codice:
+
+```js
+function updateElement(id, textOrNode) {
+ const element = document.getElementById(id);
+ element.textContent = ''; // Rimuove tutti i figli
+ element.append(textOrNode);
+}
+```
+
+Si usa il metodo [`append()`](https://developer.mozilla.org/en-US/docs/Web/API/ParentNode/append) in quanto consente di allegare testo o [nodi DOM](https://developer.mozilla.org/en-US/docs/Web/API/Node) a un elemento genitore, che è perfetto per tutti i casi d'uso.
+
+Se si prova a utilizzare l'account `test` per accedere, ora si dovrebbe vedere un elenco di transazioni sul cruscotto 🎉.
+
+---
+
+## 🚀 Sfida
+
+Collaborare per far sembrare la pagina del cruscotto una vera app bancaria. Se è già stato definito lo stile della propria app, provare a utilizzare le [media query](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries) per creare una [disposizione reattiva](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Responsive/responsive_design_building_blocks) che funzioni bene sia su dispositivi desktop che mobili.
+
+Ecco un esempio di una pagina cruscotto con applicato uno stile:
+
+![Videata di un risultato di esempio del cruscotto dopo l'applicazione dello stile](../../images/screen2.png)
+
+## Quiz Post-Lezione
+
+[Quiz post-lezione](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/46?loc=it)
+
+## Compito
+
+[Refattorizzare e commentare il codice](assignment.it.md)
diff --git a/7-bank-project/3-data/translations/README.ja.md b/7-bank-project/3-data/translations/README.ja.md
index c1f6e57c..ecec6b03 100644
--- a/7-bank-project/3-data/translations/README.ja.md
+++ b/7-bank-project/3-data/translations/README.ja.md
@@ -321,7 +321,7 @@ function updateElement(id, textOrNode) {
ダッシュボードページのスタイリング例です。
-![スタイリング後のダッシュボードの結果例のスクリーンショット](../images/screen2.png)
+![スタイリング後のダッシュボードの結果例のスクリーンショット](../../images/screen2.png)
## レッスン後の小テスト
diff --git a/7-bank-project/3-data/translations/assignment.it.md b/7-bank-project/3-data/translations/assignment.it.md
new file mode 100644
index 00000000..6baff51a
--- /dev/null
+++ b/7-bank-project/3-data/translations/assignment.it.md
@@ -0,0 +1,15 @@
+# Refattorizzare e commentare il codice
+
+## Istruzioni
+
+Man mano che la base del codice cresce, è importante rifattorizzare il codice frequentemente per mantenerlo leggibile e gestibile nel tempo. Aggiungere commenti e rifattorizzare la propria `app.js` per migliorare la qualità del codice:
+
+- Estrarre costanti, come l'URL di base dell'API del server
+- Fattorizzare codice simile: ad esempio si può creare una funzione `sendRequest()` per raggruppare il codice utilizzato sia in `createAccount()` che in `getAccount()`
+- Riorganizzare il codice per renderlo più facile da leggere e aggiungere commenti
+
+## Rubrica
+
+| Criteri | Ottimo | Adeguato | Necessita miglioramento |
+| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
+| | Il codice è commentato, ben organizzato in diverse sezioni e di facile lettura. Le costanti vengono estratte ed è stata creata una funzione `sendRequest()` fattorizzata. | Il codice è pulito ma può ancora essere migliorato con più commenti, estrazione di costanti o fattorizzazione. | Il codice è disordinato, non commentato, le costanti non vengono estratte e il codice non è fattorizzato |
diff --git a/7-bank-project/4-state-management/README.md b/7-bank-project/4-state-management/README.md
index 2901fd06..689335e0 100644
--- a/7-bank-project/4-state-management/README.md
+++ b/7-bank-project/4-state-management/README.md
@@ -31,7 +31,7 @@ There's 3 issues with the current code:
- The state is not persisted, as a browser refresh takes you back to the login page.
- There are multiple functions that modify the state. As the app grows, it can make it difficult to track the changes and it's easy to forget updating one.
-- The state is not cleaned up, when you click on *Logout* the account data is still there even though you're on the login page.
+- The state is not cleaned up, so when you click on *Logout* the account data is still there even though you're on the login page.
We could update our code to tackle these issues one by one, but it would create more code duplication and make the app more complex and difficult to maintain. Or we could pause for a few minutes and rethink our strategy.
@@ -42,7 +42,7 @@ We could update our code to tackle these issues one by one, but it would create
- How to keep the data flows in an app understandable?
- How to keep the state data always in sync with the user interface (and vice versa)?
-Once you've taken care of these, any other issues you might have may either be fixed already or have become easier to fix. There are many possible approaches for solving these problems, but we'll go with a common solution that consists in **centralizing the data and the ways to change it**. The data flows would go like this:
+Once you've taken care of these, any other issues you might have may either be fixed already or have become easier to fix. There are many possible approaches for solving these problems, but we'll go with a common solution that consists of **centralizing the data and the ways to change it**. The data flows would go like this:
![Schema showing the data flows between the HTML, user actions and state](./images/data-flow.png)
@@ -82,7 +82,7 @@ This refactoring by itself did not bring much improvements, but the idea was to
Now that we have put in place the `state` object to store our data, the next step is centralize the updates. The goal is to make it easier to keep track of any changes and when they happen.
-To avoid having changes made to the `state` object it's also a good practice to consider it [*immutable*](https://en.wikipedia.org/wiki/Immutable_object), meaning that it cannot be modified at all. It also means that you have to create a new state object if you want to change anything in it. By doing this, you build a protection about potentially unwanted [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)), and open up possibilities for new features in your app like implementing undo/redo, while also making it easier to debug. For example, you could log every changes made to the state and keep an history of the changes to understand the source of a bug.
+To avoid having changes made to the `state` object, it's also a good practice to consider it [*immutable*](https://en.wikipedia.org/wiki/Immutable_object), meaning that it cannot be modified at all. It also means that you have to create a new state object if you want to change anything in it. By doing this, you build a protection about potentially unwanted [side effects](https://en.wikipedia.org/wiki/Side_effect_(computer_science)), and open up possibilities for new features in your app like implementing undo/redo, while also making it easier to debug. For example, you could log every change made to the state and keep a history of the changes to understand the source of a bug.
In JavaScript, you can use [`Object.freeze()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) to create an immutable version of an object. If you try to make changes to an immutable object, an exception will be raised.
@@ -195,9 +195,9 @@ init();
Here we retrieve the saved data, and if there's any we update the state accordingly. It's important to do this *before* updating the route, as there might be code relying on the state during the page update.
-We can also make the *Dashboard* page our application default page, as we are now persisting the account data. If no data is found, the dashboard takes care of redirecting to the *Login* page anyways. In `updateRoute()`, replace the fallback `return navigate('/login');` with `return navigate('dashboard');`.
+We can also make the *Dashboard* page our application default page, as we are now persisting the account data. If no data is found, the dashboard takes care of redirecting to the *Login* page anyways. In `updateRoute()`, replace the fallback `return navigate('/login');` with `return navigate('/dashboard');`.
-Now login in the app and try refreshing the page, you should stay on the dashboard. With that update we've taken care of all our initial issues...
+Now login in the app and try refreshing the page. You should stay on the dashboard. With that update we've taken care of all our initial issues...
## Refresh the data
diff --git a/7-bank-project/4-state-management/translations/README.it.md b/7-bank-project/4-state-management/translations/README.it.md
new file mode 100644
index 00000000..2af21d74
--- /dev/null
+++ b/7-bank-project/4-state-management/translations/README.it.md
@@ -0,0 +1,281 @@
+# Creare un'App Bancaria Parte 4: Concetti di Gestione dello Stato
+
+## Quiz Pre-Lezione
+
+[Quiz Pre-Lezione](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/47?loc=it)
+
+### Introduzione
+
+Man mano che un'applicazione web cresce, diventa una sfida tenere traccia di tutti i flussi di dati. Quale codice riceve i dati, quale pagina li consuma, dove e quando deve essere aggiornata ... è facile ritrovarsi con codice disordinato e difficile da mantenere. Ciò è particolarmente vero quando è necessario condividere dati tra diverse pagine della propria app, ad esempio i dati dell'utente. Il concetto di *gestione dello stato* è sempre esistito in tutti i tipi di programmi, ma poiché le app web continuano a crescere in complessità, ora è un punto chiave su cui riflettere durante lo sviluppo.
+
+In questa parte finale, si esaminerà l'app creata per ripensare a come viene gestito lo stato, consentendo il supporto per l'aggiornamento del browser in qualsiasi momento e persistendo i dati tra le sessioni utente.
+
+### Prerequisito
+
+È necessario aver completato la parte di [recupero dei dati](../../3-data/translations/README.it.md) dell'app web per questa lezione. È inoltre necessario installare [Node.js](https://nodejs.org) ed [eseguire l'API del server](../../api/translations/README.it.md) in locale in modo da ottenere i dati dell'account.
+
+Si può verificare che il server funzioni correttamente eseguendo questo comando in un terminale:
+
+```sh
+curl http://localhost:5000/api
+# -> dovrebbe restituire "Bank API v1.0.0" come risultato
+```
+
+---
+
+## Ripensare la gestione dello stato
+
+Nella [lezione precedente](../../3-data/translations/README.it.md), è stato introdotto un concetto basico di stato nell'app con la variabile globale `account` che contiene i dati bancari per l'utente attualmente connesso. Tuttavia, l'attuale implementazione presenta alcuni difetti. Si provi ad aggiornare la pagina quando ci si trova nella pagina del cruscotto. Che cosa accade?
+
+Ci sono 3 problemi con il codice corrente:
+
+- Lo stato non è persistente, poiché un aggiornamento del browser riporta alla pagina di accesso.
+- Esistono più funzioni che modificano lo stato. Man mano che l'app cresce, può essere difficile tenere traccia delle modifiche ed è facile dimenticare di aggiornarne una.
+- Lo stato non viene cancellato, quando si fa clic su *Logout* i dati dell'account sono ancora lì anche se si è nella pagina di accesso.
+
+Si potrebbe aggiornare il codice per affrontare questi problemi uno per uno, ma creerebbe più duplicazioni del codice e renderebbe l'app più complessa e difficile da mantenere. Oppure ci si potrebbe fermare per qualche minuto e ripensare alla strategia.
+
+> Quali problemi si stanno davvero cercando di risolvere qui?
+
+La [gestione dello stato](https://en.wikipedia.org/wiki/State_management) consiste nel trovare un buon approccio per risolvere questi due problemi particolari:
+
+- Come mantenere comprensibile il flusso di dati in un'app?
+- Come mantenere i dati di stato sempre sincronizzati con l'interfaccia utente (e viceversa)?
+
+Una volta che ci si è preso cura di questi, qualsiasi altro problema che si potrebbe avere potrebbe essere già stato risolto o essere diventato più facile da sistemare. Ci sono molti possibili approcci per risolvere questi problemi, ma si andrà con una soluzione comune che consiste nel **centralizzare i dati e le modalità per cambiarli**. Il flusso di dati andrebbe così:
+
+![Schema che mostra i flussi di dati tra HTML, azioni dell'utente e stato](../images/data-flow.png)
+
+> Non verrà trattata qui la parte in cui i dati attivano automaticamente l'aggiornamento della vista, poiché è legato a concetti più avanzati di [programmazione reattiva](https://en.wikipedia.org/wiki/Reactive_programming). È un buon argomento da sviluppare successivamente se si è pronti per un'immersione profonda.
+
+✅ Esistono molte librerie con approcci diversi alla gestione dello stato, [Redux](https://redux.js.org) è un'opzione popolare. Dare un'occhiata ai concetti e ai modelli utilizzati spesso è un buon modo per apprendere quali potenziali problemi si potrebbe dover affrontare nelle grandi app web e come risolverli.
+
+### Attività
+
+Si inizierà con un po' di refattorizzazione. Sostituire la dichiarazione di `account` :
+
+```js
+let account = null;
+```
+
+Con:
+
+```js
+let state = {
+ account: null
+};
+```
+
+L'idea è *centralizzare* tutti i dati dell'app in un unico oggetto di stato. Per ora c'è solo `account` nello stato, quindi non cambia molto, ma crea un percorso per le evoluzioni.
+
+Si devono anche aggiornare le funzioni che lo utilizzano. Nelle funzioni `register()` e `login()` , sostituire `account = ...` con `state.account = ...`;
+
+Nella parte superiore della funzione `updateDashboard()`, aggiungere questa riga:
+
+```js
+const account = state.account;
+```
+
+Questa refattorizzazione di per sé non ha portato molti miglioramenti, ma l'idea era di gettare le basi per i prossimi cambiamenti.
+
+## Tenere traccia delle modifiche ai dati
+
+Ora che si è impostato l'oggetto `state` per memorizzare i dati, il passaggio successivo è centralizzare gli aggiornamenti. L'obiettivo è rendere più facile tenere traccia di eventuali modifiche e quando si verificano.
+
+Per evitare che vengano apportate modifiche all'oggetto `state` è anche una buona pratica considerarlo [*immutabile*](https://en.wikipedia.org/wiki/Immutable_object), nel senso che non può essere modificato affatto. Significa anche che si deve creare un nuovo oggetto di stato se si vuole cambiare qualcosa in esso. In questo modo, si crea una protezione [dagli effetti collaterali](https://it.wikipedia.org/wiki/Effetto_collaterale_(informatica)) potenzialmente indesiderati e si aprono possibilità per nuove funzionalità nella propria app come l'implementazione di funzioni di annulla/ripristina, semplificando anche il debug. Ad esempio, è possibile registrare tutte le modifiche apportate allo stato e conservare una cronologia delle modifiche per comprendere l'origine di un bug.
+
+In JavaScript, si può utilizzare [`Object.freeze()`](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) per creare una versione immutabile di un oggetto. Se si prova ad apportare modifiche a un oggetto immutabile, verrà sollevata un'eccezione.
+
+✅ Si conosce la differenza tra un oggetto *shallow* e uno *deep* immutabile? Si può leggere [qui](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze) per saperne di più.
+
+### Attività
+
+Creare una nuova funzione `updateState()` :
+
+```js
+function updateState(property, newData) {
+ state = Object.freeze({
+ ...state,
+ [property]: newData
+ });
+}
+```
+
+In questa funzione, si crea un nuovo oggetto di stato e si copiano i dati dallo stato precedente utilizzando l' [*operatore spread (`...`)*](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Operators/Spread_syntax). Quindi si sovrascrive una particolare proprietà dell'oggetto state con i nuovi dati usando la [notazione tra parentesi quadre](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) `[property]` per l'assegnazione. Infine, si blocca l'oggetto per impedire modifiche utilizzando `Object.freeze()`. Per ora si ha solo la proprietà `account` memorizzata nello stato, ma con questo approccio si possono aggiungere tutte le proprietà che servono nello stato.
+
+Si aggiornerà anche l'inizializzazione di `state` per assicurarsi che anche lo stato iniziale sia congelato:
+
+```js
+let state = Object.freeze({
+ account: null
+});
+```
+
+Successivamente, aggiornare la funzione `register` sostituendo l'istruzione `state.account = result;` con:
+
+```js
+updateState('account', result);
+```
+
+Fare lo stesso con la funzione `login` , sostituendo `state.account = data;` con:
+
+```js
+updateState('account', data);
+```
+
+Si coglie ora l'occasione per risolvere il problema della mancata cancellazione dei dati dell'account quando l'utente fa clic su *Logout*.
+
+Creare una nuova funzione `logout ()`:
+
+```js
+function logout() {
+ updateState('account', null);
+ navigate('/login');
+}
+```
+
+In `updateDashboard()`, sostituire il reindirizzamento `return navigate('/ login');` con `return logout()`;
+
+Provare a registrare un nuovo account, a disconnettersi e ad accedere nuovamente per verificare che tutto funzioni ancora correttamente.
+
+> Suggerimento: si può dare un'occhiata a tutti i cambiamenti di stato aggiungendo `console.log (state)` nella parte inferiore di `updateState()` e aprendo la console negli strumenti di sviluppo del browser.
+
+## Persistere lo stato
+
+La maggior parte delle app web deve conservare i dati per poter funzionare correttamente. Tutti i dati critici vengono solitamente archiviati su un database e accessibili tramite un'API del server, come nel nostro caso i dati dell'account utente. Ma a volte è anche interessante mantenere alcuni dati sulla parte client dell'app in esecuzione nel browser, per una migliore esperienza utente o per migliorare le prestazioni di caricamento.
+
+Quando si vuole mantenere i dati nel browser, ci sono alcune domande importanti da porsi:
+
+- *I dati sono sensibili?* Si dovrebbe evitare di memorizzare dati sensibili sul client, come le password degli utenti.
+- *Per quanto tempo si ha bisogno di conservare questi dati?* Si prevede di accedere a questi dati solo per la sessione corrente o si desidera che vengano memorizzati per sempre?
+
+Esistono diversi modi per archiviare le informazioni all'interno di un'app web, a seconda di ciò che si desidera ottenere. Ad esempio, si possono utilizzare gli URL per memorizzare una interrogazione di ricerca e renderla condivisibile tra gli utenti. Si possono anche utilizzare i [cookie HTTP](https://developer.mozilla.org/it/docs/Web/HTTP/Cookies) se i dati devono essere condivisi con il server, come le informazioni di [autenticazione](https://it.wikipedia.org/wiki/Autenticazione) .
+
+Un'altra opzione è utilizzare una delle tante API del browser per la memorizzazione dei dati. Due di loro sono particolarmente interessanti:
+
+- [`localStorage`](https://developer.mozilla.org/it/docs/Web/API/Window/localStorage): un [archivio chiave/valore](https://en.wikipedia.org/wiki/Key%E2%80%93value_database) che consente di persistere i dati specifici del sito Web corrente in diverse sessioni. I dati salvati in esso non scadono mai.
+- [`sessionStorage`](https://developer.mozilla.org/it/docs/Web/API/Window/sessionStorage): funziona come `localStorage` tranne per il fatto che i dati in esso memorizzati vengono cancellati al termine della sessione (alla chiusura del browser).
+
+Notare che entrambe queste API consentono solo di memorizzare [stringhe](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/String). Se si desidera archiviare oggetti complessi, si dovranno serializzare nel formato [JSON](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/JSON) utilizzando [`JSON.stringify()`](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).
+
+✅ Se si desidera creare un'app web che non funziona con un server, è anche possibile creare un database sul client utilizzando l' [`API` IndexedDB](https://developer.mozilla.org/it/docs/Web/API/IndexedDB_API). Questo è riservato a casi d'uso avanzati o se è necessario archiviare una quantità significativa di dati, poiché è più complesso da usare.
+
+### Attività
+
+Si vuole che gli utenti rimangano collegati fino a quando non fanno clic esplicitamente sul pulsante *Logout* , quindi si utilizzerà `localStorage` per memorizzare i dati dell'account. Per prima cosa, si definisce una chiave che verrà usata per memorizzare i dati.
+
+```js
+const storageKey = 'savedAccount';
+```
+
+Aggiungere quindi questa riga alla fine della funzione `updateState()`:
+
+```js
+localStorage.setItem(storageKey, JSON.stringify(state.account));
+```
+
+Con questo, i dati dell'account utente verranno mantenuti e sempre aggiornati poiché si sono centralizzati in precedenza tutti gli aggiornamenti di stato. È qui che si inizia a trarre vantaggio da tutte le rifattorizzazioni precedenti 🙂.
+
+Poiché i dati vengono salvati, ci si deve anche occupare di ripristinarli quando l'app viene caricata. Dato che si inizierà ad avere più codice di inizializzazione, potrebbe essere una buona idea creare una nuova funzione di inizializzazione `init` , che includa anche il codice precedente nella parte inferiore di `app.js`:
+
+```js
+function init() {
+ const savedAccount = localStorage.getItem(storageKey);
+ if (savedAccount) {
+ updateState('account', JSON.parse(savedAccount));
+ }
+
+ // Il codice di inizializzazione precedente
+ window.onpopstate = () => updateRoute();
+ updateRoute();
+}
+
+init();
+```
+
+Qui si recuperano i dati salvati e, se ce ne sono, si aggiorna lo stato di conseguenza. È importante farlo *prima* di aggiornare la rotta, poiché potrebbe esserci del codice che si basa sullo stato durante l'aggiornamento della pagina.
+
+Si può anche rendere la pagina del *cruscotto* la pagina predefinita dell'applicazione, poiché ora si sta persistendo i dati dell'account. Se non vengono trovati dati, il cruscotto si occupa comunque di reindirizzare alla pagina di *Login* . In `updateRoute()`, sostituire le istruzioni di contingenza `return navigate ('/login');` con `return navigate ('/dashboard') ;`.
+
+Ora accedere all'app e provare ad aggiornare la pagina, si dovrebbe rimanere sul cruscotto. Con quell'aggiornamento ci si è presi cura di tutti i problemi iniziali...
+
+## Aggiornare i dati
+
+...Si potrebbe uttavia anche averne creato uno nuovo. Oops!
+
+Andare al cruscotto utilizzando l'account `test`, quindi eseguire questo comando su un terminale per creare una nuova transazione:
+
+```sh
+curl --request POST \
+ --header "Content-Type: application/json" \
+ --data "{ \"date\": \"2020-07-24\", \"object\": \"Bought book\", \"amount\": -20 }" \
+ http://localhost:5000/api/accounts/test/transactions
+```
+
+Provare subito ad aggiornare la pagina del cruscotto nel browser. Che cosa accade? Si vede la nuova transazione?
+
+Lo stato viene mantenuto indefinitamente grazie a `localStorage`, ma ciò significa anche che non viene aggiornato fino a quando non si esce dall'app e si accede di nuovo!
+
+Una possibile strategia per risolvere questo problema è ricaricare i dati dell'account ogni volta che viene caricato il cruscotto, per evitare lo stallo dei dati.
+
+### Attività
+
+Creare una nuova funzione `updateAccountData`:
+
+```js
+async function updateAccountData() {
+ const account = state.account;
+ if (!account) {
+ return logout();
+ }
+
+ const data = await getAccount(account.user);
+ if (data.error) {
+ return logout();
+ }
+
+ updateState('account', data);
+}
+```
+
+Questo metodo controlla che si sia attualmente collegati, quindi ricarica i dati dell'account dal server.
+
+Creare un'altra funzione chiamata `refresh`:
+
+```js
+async function refresh() {
+ await updateAccountData();
+ updateDashboard();
+}
+```
+
+Questa aggiorna i dati dell'account, quindi si occupa dell'aggiornamento dell'HTML della pagina del cruscotto. È ciò che si deve chiamare quando viene caricata la rotta del cruscotto (dashboard). Aggiornare la definizione del percorso con:
+
+```js
+const routes = {
+ '/login': { templateId: 'login' },
+ '/dashboard': { templateId: 'dashboard', init: refresh }
+};
+```
+
+Provare a ricaricare il cruscotto ora, dovrebbe visualizzare i dati dell'account aggiornati.
+
+---
+
+## 🚀 Sfida
+
+Ora che i dati dell'account vengono ricaricati ogni volta che viene caricato il cruscotto, si pensa che sia ancora necessario persistere *tutti i dati dell'account* ?
+
+Provare a lavorare insieme per cambiare ciò che viene salvato e caricato da `localStorage` per includere solo ciò che è assolutamente necessario per il funzionamento dell'app.
+
+## Quiz Post-Lezione
+
+[Quiz post-lezione](https://nice-beach-0fe9e9d0f.azurestaticapps.net/quiz/48?loc=it)
+
+## Compito
+
+[Implementare la finestra di dialogo "Aggiungi transazione"](assignment.it.md)
+
+Ecco un esempio di risultato dopo aver completato il compito:
+
+![Videata che mostra un esempio di dialogo "Aggiungi transazione"](../images/dialog.png)
diff --git a/7-bank-project/4-state-management/translations/README.ja.md b/7-bank-project/4-state-management/translations/README.ja.md
index 46592e0c..6f630f96 100644
--- a/7-bank-project/4-state-management/translations/README.ja.md
+++ b/7-bank-project/4-state-management/translations/README.ja.md
@@ -12,7 +12,7 @@ Web アプリケーションが成長するにつれて、すべてのデータ
### 前提条件
-このレッスンでは、Web アプリの[データ取得](./././3-data/translations/README.ja.md)の部分が完了している必要があります。また、アカウントデータを管理するためには、ローカルに [Node.js](https://nodejs.org/ja) をインストールし、[サーバー API を実行する](.../../api/translations/README.ja.md)をインストールする必要があります。
+このレッスンでは、Web アプリの[データ取得](../../3-data/translations/README.ja.md)の部分が完了している必要があります。また、アカウントデータを管理するためには、ローカルに [Node.js](https://nodejs.org/ja) をインストールし、[サーバー API を実行する](../../api/translations/README.ja.md)をインストールする必要があります。
ターミナルでこのコマンドを実行することで、サーバーが正常に動作しているかどうかをテストすることができます。
@@ -82,7 +82,7 @@ const account = state.account;
データを保存するために `state` オブジェクトを配置したので、次のステップは更新を一元化することです。目的は、いつ変更があったのか、いつ変更が発生したのかを簡単に把握できるようにすることです。
-`state` オブジェクトに変更が加えられないようにするためには、`state` オブジェクトを [*immutable*](https://en.wikipedia.org/wiki/Immutable_object) と考えるのも良い方法です。これはまた、何かを変更したい場合には新しいステートオブジェクトを作成しなければならないことを意味します。このようにすることで、潜在的に望ましくない[副作用](https://en.wikipedia.org/wiki/Side_effect_(computer_science)についての保護を構築し、アンドゥ/リドゥの実装のようなアプリの新機能の可能性を開くと同時に、デバッグを容易にします。例えば、ステートに加えられたすべての変更をログに記録し、バグの原因を理解するために変更の履歴を保持することができます。
+`state` オブジェクトに変更が加えられないようにするためには、`state` オブジェクトを [*immutable*](https://en.wikipedia.org/wiki/Immutable_object) と考えるのも良い方法です。これはまた、何かを変更したい場合には新しいステートオブジェクトを作成しなければならないことを意味します。このようにすることで、潜在的に望ましくない[副作用](https://ja.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0))についての保護を構築し、アンドゥ/リドゥの実装のようなアプリの新機能の可能性を開くと同時に、デバッグを容易にします。例えば、ステートに加えられたすべての変更をログに記録し、バグの原因を理解するために変更の履歴を保持することができます。
JavaScript では、[`Object.freeze()`](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) を使って、オブジェクトの不変バージョンを作成することができます。不変オブジェクトに変更を加えようとすると例外が発生します。
diff --git a/7-bank-project/4-state-management/translations/assignment.it.md b/7-bank-project/4-state-management/translations/assignment.it.md
new file mode 100644
index 00000000..0b665b7d
--- /dev/null
+++ b/7-bank-project/4-state-management/translations/assignment.it.md
@@ -0,0 +1,25 @@
+# Implementare la finestra di dialogo "Aggiungi transazione"
+
+## Istruzioni
+
+All'app bancaria manca ancora una caratteristica importante: la possibilità di inserire nuove transazioni.
+Utilizzando tutto quanto appreso nelle quattro lezioni precedenti, implementare una finestra di dialogo "Aggiungi transazione":
+
+- Aggiungere un pulsante "Aggiungi transazione" nella pagina del cruscotto
+- Creare una nuova pagina con un modello HTML o usare JavaScript per mostrare/nascondere l'HTML della finestra di dialogo senza lasciare la pagina del cruscotto (si può usare la proprietà [`hidden`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/hidden) per quello o le classi CSS)
+- Assicurarsi di gestire l' [accessibilità dalla tastiera e dal lettore di schermo](https://developer.paciellogroup.com/blog/2018/06/the-current-state-of-modal-dialog-accessibility/) per la finestra di dialogo
+- Implementare un form HTML per ricevere i dati di input
+- Creare dati JSON dai dati del form e inviarli all'API
+- Aggiorna la pagina del cruscotto con i nuovi dati
+
+Guardare [le specifiche dell'API del server](../api/README.md) per vedere quale API si devono chiamare e qual è il formato JSON previsto.
+
+Ecco un esempio di risultato dopo aver completato il compito:
+
+![Videata che mostra un esempio di dialogo "Aggiungi transizione"](../images/dialog.png)
+
+## Rubrica
+
+| Criteri | Ottimo | Adeguato | Necessita miglioramento |
+| -------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------|
+| | L'aggiunta di una transazione viene implementata seguendo completamente tutte le migliori pratiche viste nelle lezioni. | L'aggiunta di una transazione è implementata, ma non seguendo le migliori pratiche viste nelle lezioni o funzionante solo parzialmente. | L'aggiunta di una transazione non funziona affatto. |
diff --git a/7-bank-project/4-state-management/translations/assignment.ja.md b/7-bank-project/4-state-management/translations/assignment.ja.md
index f1b25f22..b707bf65 100644
--- a/7-bank-project/4-state-management/translations/assignment.ja.md
+++ b/7-bank-project/4-state-management/translations/assignment.ja.md
@@ -16,7 +16,7 @@
以下は、課題を完了した後の結果の例です。
-![「トランジションの追加」ダイアログの例を示すスクリーンショット](../../images/dialog.png)
+![「トランジションの追加」ダイアログの例を示すスクリーンショット](../images/dialog.png)
## ルーブリック
diff --git a/7-bank-project/api/translations/README.it.md b/7-bank-project/api/translations/README.it.md
new file mode 100644
index 00000000..f4e0ba50
--- /dev/null
+++ b/7-bank-project/api/translations/README.it.md
@@ -0,0 +1,33 @@
+# API Bank
+
+> Bank API è costruita con [Node.js](https://nodejs.org) + [Express](https://expressjs.com/).
+
+L'API è già costruita e non fa parte dell'esercizio.
+
+Tuttavia, se interessa imparare come creare un'API come questa, si può seguire questa serie di video: https://aka.ms/NodeBeginner (i video da 17 a 21 riguardano questa specifica API).
+
+Si può anche dare un'occhiata a questo tutorial interattivo: https://aka.ms/learn/express-api
+
+## Mettere in esecuzione il server
+
+Assicurarsi di aver [installato](https://nodejs.org) Node.js.
+
+1. Eseguire il comando `git clone` per questo repository.
+2. Aprire un terminale nella cartella `api` , quindi eseguire `npm install`.
+3. Eseguire `npm start`.
+
+Il server dovrebbe mettersi in ascolto sulla porta `5000`.
+
+> Nota: tutte le voci vengono archiviate in memoria e non sono persistenti, quindi quando il server viene arrestato tutti i dati vengono persi.
+
+## Dettagli API
+
+| Rotta | Descrizione |
+---------------------------------------------|------------------------------------
+| GET /api/ | Ottiene informazioni sul server |
+| POST /api/accounts/ | Crea un account, ad es.: `{user: "Giovanni", description: "Il mio budget", currency: "EUR", balance: 100}` |
+| GET /api/accounts/:user | Ottiene tutti i dati per l'account specificato |
+| DELETE /api/accounts/: user | Rimuove l'account specificato |
+| POST /api/account/:user/transactions | Aggiunge una transazione, ad es .: `{date: '2020-07-23T18:25:43.511Z', object: "Acquistato un libro", amount: -20}` |
+| DELETE /api/accounts/:user/transactions/:id | Rimuove la transazione specificata |
+
diff --git a/7-bank-project/solution/translations/README.it.md b/7-bank-project/solution/translations/README.it.md
new file mode 100644
index 00000000..ad75f742
--- /dev/null
+++ b/7-bank-project/solution/translations/README.it.md
@@ -0,0 +1,13 @@
+# App Bancaria
+
+> Soluzione di esempio per il progetto app bancaria, costruito con semplice HTML5, CSS e JavaScript (non è stata usato alcun framework o libreria).
+
+## Eseguire l'app
+
+Per prima cosa assicurarsi di avere in esecuzione il [server API](../../api/translations/README.it.md).
+
+Può essere usato un qualsiasi server web per eseguire l'app, ma visto che si dovrebbe avere installato comunque [Node.js](https://nodejs.org) per eseguire l'API, è possibile:
+
+1. Utilizzare il comando `git clone` con questo repository.
+2. Aprire un terminale, poi eseguire `npx lite-server solution`. Verrà fatto partire un server web di sviluppo sulla porta `3000`
+3. Aprire `http://localhost:3000` in un browser per eseguire l'app.
diff --git a/7-bank-project/translations/README.it.md b/7-bank-project/translations/README.it.md
new file mode 100644
index 00000000..1c8aae8d
--- /dev/null
+++ b/7-bank-project/translations/README.it.md
@@ -0,0 +1,21 @@
+# :dollar: Costruire una Banca
+
+In questo progetto si imparerà come costruire una banca immaginaria. Queste lezioni includono istruzioni su come disporre un'app web e fornire rotte, creare form, gestire lo stato e recuperare dati da un'API da cui è possibile ottenere i dati della banca.
+
+| ![Videata1](../images/screen1.png) | ![Videata2](../images/screen2.png) |
+|--------------------------------|--------------------------------|
+
+## Lezioni
+
+1. [Modelli HTML e Rotte in un'app Web](../1-template-route/translations/README.it.md)
+2. [Creare un Form di Accesso e Registrazione](../2-forms/translations/README.it.md)
+3. [Metodi di Recupero e Utilizzo Dati](../3-data/translations/README.it.md)
+4. [Concetti di Gestione dello Stato](../4-state-management/translations/README.it.md)
+
+### Crediti
+
+Queste lezioni sono state scritte con il :hearts: da [Yohan Lasorsa](https://twitter.com/sinedied).
+
+Se interessati a imparare come costruire l' [API del server](../../api/tranlations/README.it.md) utilizzata in queste lezioni, è possibile seguire [questa serie di video](https://aka.ms/NodeBeginner) (in particolare i video da 17 a 21).
+
+Si può anche dare un'occhiata a [questo tutorial interattivo di apprendimento](https://aka.ms/learn/express-api).
\ No newline at end of file
diff --git a/TRANSLATIONS.md b/TRANSLATIONS.md
index 81e3ef90..3b43ea3a 100644
--- a/TRANSLATIONS.md
+++ b/TRANSLATIONS.md
@@ -6,12 +6,18 @@ We welcome translations for the lessons in this curriculum!
There are [**translations**](https://github.com/microsoft/Web-Dev-For-Beginners/tree/main/1-getting-started-lessons/1-intro-to-programming-languages/translations) folders which contain the translated markdown files.
-Translated lessons should follow this naming convention:
+> Note, please do not translate any code in the code sample files; the only things to translate are README, assignments, and the quizzes. Thanks!
+
+Translated files should follow this naming convention:
**README._[language]_.md**
where _[language]_ is a two letter language abbreviation following the ISO 639-1 standard (e.g. `README.es.md` for Spanish and `README.nl.md` for Dutch).
+**assignment._[language]_.md**
+
+Similar to Readme's, please translate the assignments as well.
+
**Quizzes**
1. Add your translation to the quiz-app by adding a file here: https://github.com/microsoft/Web-Dev-For-Beginners/tree/main/quiz-app/src/assets/translations, with proper naming convention (en.json, fr.json). **Please don't localize the words 'true' or 'false' however. thanks!**
diff --git a/lesson-template/translations/.github/post-lecture-quiz.hi.md b/lesson-template/translations/.github/post-lecture-quiz.hi.md
deleted file mode 100644
index 928337d7..00000000
--- a/lesson-template/translations/.github/post-lecture-quiz.hi.md
+++ /dev/null
@@ -1,24 +0,0 @@
-_प्रति प्रश्न के एक उत्तर की जाँच करके अपने प्रस्तुतिकरण के साथ इस प्रश्नोत्तरी को पूरा करें._
-
-क्विज़ को पूरा करने के लिए आपको निम्नलिखित लर्निंग मॉड्यूल(एस) को पूरा करना होगा:
-
-[लर्न लिंक १]()
-[लर्न लिंक २]()
-
-1. [Q1]
-
-- [ ] [विकल्प १]
-- [ ] [विकल्प २]
-- [ ] [विकल्प ३]
-
-2. [Q2]
-
-- [ ] [विकल्प १]
-- [ ] [विकल्प २]
-- [ ] [विकल्प ३]
-
-3. [Q3]
-
-- [ ] [विकल्प १]
-- [ ] [विकल्प २]
-- [ ] [विकल्प ३]
diff --git a/lesson-template/translations/.github/pre-lecture-quiz.hi.md b/lesson-template/translations/.github/pre-lecture-quiz.hi.md
deleted file mode 100644
index 5bf490b3..00000000
--- a/lesson-template/translations/.github/pre-lecture-quiz.hi.md
+++ /dev/null
@@ -1,19 +0,0 @@
-_इस क्विज को कक्षा में पूरा करें_
-
-1. [Q1]
-
-- [ ] [विकल्प १]
-- [ ] [विकल्प २]
-- [ ] [विकल्प ३]
-
-2. [Q2]
-
-- [ ] [विकल्प १]
-- [ ] [विकल्प २]
-- [ ] [विकल्प ३]
-
-3. [Q3]
-
-- [ ] [विकल्प १]
-- [ ] [विकल्प २]
-- [ ] [विकल्प ३]
diff --git a/translations/README.ja.md b/translations/README.ja.md
index 31613077..db1a236e 100644
--- a/translations/README.ja.md
+++ b/translations/README.ja.md
@@ -8,7 +8,7 @@
> **学生の皆さん**、このカリキュラムを自分で使うためには、リポジトリ全体をフォークして、講義前の小テストから始めて、講義を読んで、残りのアクティビティを自分で完成させてください。解答コードは各レッスンの /solutions フォルダにありますが、解答コードをコピーするのではなく、授業を理解した上でプロジェクトを作成するようにしてください。また、友達と勉強会を作って、一緒に勉強するのもいいでしょう。さらに勉強するには、[Microsoft Learn](https://docs.microsoft.com/users/jenlooper-2911/collections/jg2gax8pzd6o81?WT.mc_id=academic-13441-cxa) や以下のビデオを見ることをお勧めします。
-[![Promo video](screenshot.png)](https://youtube.com/watch?v=R1wrdtmBSII "Promo video")
+[![Promo video](../screenshot.png)](https://youtube.com/watch?v=R1wrdtmBSII "Promo video")
> 上の画像をクリックすると、プロジェクトとそれを作成した人々についてのビデオを見ることができます。