# Construiește o Aplicație Bancară Partea 3: Metode de Preluare și Utilizare a Datelor Gândește-te la computerul Enterprise din Star Trek - când Căpitanul Picard cere starea navei, informația apare instantaneu fără ca întreaga interfață să se închidă și să se reconstruiască. Acest flux lin de informații este exact ceea ce construim aici cu preluarea dinamică a datelor. În acest moment, aplicația ta bancară este ca un ziar tipărit - informativă, dar statică. Vom transforma aplicația într-un ceva mai asemănător centrului de comandă de la NASA, unde datele curg continuu și se actualizează în timp real fără a întrerupe fluxul de lucru al utilizatorului. Vei învăța cum să comunici cu serverele asincron, să gestionezi datele care sosesc în momente diferite și să transformi informațiile brute în ceva semnificativ pentru utilizatorii tăi. Aceasta este diferența dintre un demo și un software gata pentru producție. ## ⚡ Ce Poți Face în Următoarele 5 Minute **Cale Rapidă pentru Dezvoltatori Ocupați** ```mermaid flowchart LR A[⚡ 5 minute] --> B[Configurează serverul API] B --> C[Testare preluare cu curl] C --> D[Creează funcția de autentificare] D --> E[Vezi datele în acțiune] ``` - **Minutele 1-2**: Pornește serverul tău API (`cd api && npm start`) și testează conexiunea - **Minutul 3**: Creează o funcție simplă `getAccount()` folosind fetch - **Minutul 4**: Leagă formularul de login cu `action="javascript:login()"` - **Minutul 5**: Testează login-ul și urmărește cum datele contului apar în consolă **Comenzi rapide pentru testare**: ```bash # Verificați dacă API-ul rulează curl http://localhost:5000/api # Testați preluarea datelor contului curl http://localhost:5000/api/accounts/test ``` **De ce este important**: În 5 minute vei vedea magia preluării asincrone a datelor care alimentează orice aplicație web modernă. Aceasta este fundația care face ca aplicațiile să pară receptive și vii. ## 🗺️ Călătoria Ta de Învățare prin Aplicații Web Bazate pe Date ```mermaid journey title De la pagini statice la aplicații dinamice section Înțelegerea evoluției Reîncărcări tradiționale de pagini: 3: You Descoperă beneficiile AJAX/SPA: 5: You Stăpânește modelele Fetch API: 7: You section Construirea autentificării Creează funcții de autentificare: 4: You Gestionează operații asincrone: 6: You Administrează sesiunile utilizatorului: 8: You section Actualizări dinamice ale UI-ului Învață manipularea DOM-ului: 5: You Creează afișaje pentru tranzacții: 7: You Creează tablouri de bord responsive: 9: You section Modele profesionale Redare bazată pe șabloane: 6: You Strategii de gestionare a erorilor: 7: You Optimizarea performanței: 8: You ``` **Destinația Călătoriei Tale**: La finalul acestei lecții, vei înțelege cum aplicațiile web moderne preiau, procesează și afișează date dinamic, creând experiențe de utilizator fluide pe care le așteptăm de la aplicațiile profesionale. ## Test Preliminar [Test preliminar](https://ff-quizzes.netlify.app/web/quiz/45) ### Cerințe Prealabile Înainte de a te avânta în preluarea datelor, asigură-te că ai următoarele componente pregătite: - **Lecția Anterioară**: Finalizează [Formularul de Login și Înregistrare](../2-forms/README.md) - vom construi pe această bază - **Server Local**: Instalează [Node.js](https://nodejs.org) și [pornește serverul API](../api/README.md) pentru a furniza datele contului - **Conexiune API**: Testează conexiunea serverului cu această comandă: ```bash curl http://localhost:5000/api # Răspuns așteptat: "Bank API v1.0.0" ``` Acest test rapid asigură că toate componentele comunică corect: - Verifică că Node.js rulează corect pe sistemul tău - Confirmă că serverul tău API este activ și răspunde - Validatează că aplicația ta poate accesa serverul (ca un control radio înainte de o misiune) ## 🧠 Prezentare Generală a Ecosistemului de Management al Datelor ```mermaid mindmap root((Gestionarea Datelor)) Authentication Flow Login Process Validarea Formularului Verificarea Credențialelor Gestionarea Sesiunii User State Obiectul Global al Contului Gardieni de Navigare Tratarea Erorilor API Communication Fetch Patterns Cereri GET Cereri POST Raspunsuri cu Erori Data Formats Procesarea JSON Codificarea URL Parsarea Raspunsurilor Dynamic UI Updates DOM Manipulation Actualizări Sigure de Text Crearea Elementelor Clonarea Șabloanelor User Experience Actualizări în Timp Real Mesaje de Eroare Stări de Încărcare Security Considerations XSS Prevention Utilizarea textContent Sanitizarea Inputului Crearea HTML Sigur CORS Handling Cereri Cross-Origin Configurarea Header-ului Configurare pentru Dezvoltare ``` **Principiu de bază**: Aplicațiile web moderne sunt sisteme de orchestrare a datelor - ele coordonează între interfețele utilizator, API-urile serverelor și modelele de securitate ale browserelor pentru a crea experiențe fluide și receptive. --- ## Înțelegerea Preluării Datelor în Aplicațiile Web Moderne Modul în care aplicațiile web gestionează datele s-a schimbat dramatic în ultimele două decenii. Înțelegerea acestei evoluții te va ajuta să apreciezi de ce tehnici moderne precum AJAX și Fetch API sunt atât de puternice și de ce au devenit instrumente esențiale pentru dezvoltatorii web. Să explorăm cum funcționau site-urile tradiționale comparativ cu aplicațiile dinamice și receptive pe care le construim astăzi. ### Aplicații Multi-Pagină Tradiționale (MPA) În primele zile ale web-ului, fiecare clic era ca schimbarea canalelor la un televizor vechi - ecranul devenea gol, apoi se ajusta încet către noul conținut. Aceasta era realitatea aplicațiilor web timpurii, unde fiecare interacțiune însemna reconstrucția completă a întregii pagini de la zero. ```mermaid sequenceDiagram participant User participant Browser participant Server User->>Browser: Apasă pe link sau trimite formular Browser->>Server: Solicită o pagină HTML nouă Note over Browser: Pagina devine goală Server->>Browser: Returnează pagina HTML completă Browser->>User: Afișează pagina nouă (clipire/reîncărcare) ```  **De ce această abordare părea stângace:** - Fiecare clic implica reconstruirea completă a paginii de la zero - Utilizatorii erau întrerupți în miezul gândului de acele flash-uri enervante ale paginii - Conexiunea ta la internet lucra în exces descărcând repetat același antet și subsol - Aplicațiile păreau mai mult ca navigarea prin dosare fizice decât ca utilizarea unui software ### Aplicații Moderne Single-Page (SPA) AJAX (JavaScript asincron și XML) a schimbat complet acest paradigm. Ca designul modular al Stației Spațiale Internaționale, unde astronauții pot înlocui componente individuale fără a reconstrui întreaga structură, AJAX ne permite să actualizăm părți specifice ale unei pagini web fără a reîncărca totul. Deși numele menționează XML, folosim în principal JSON astăzi, dar principiul de bază rămâne: actualizează doar ceea ce trebuie schimbat. ```mermaid sequenceDiagram participant User participant Browser participant JavaScript participant Server User->>Browser: Interacționează cu pagina Browser->>JavaScript: Declanșează handler-ul de eveniment JavaScript->>Server: Preia doar datele necesare Server->>JavaScript: Returnează date JSON JavaScript->>Browser: Actualizează elemente specifice ale paginii Browser->>User: Afișează conținut actualizat (fără reîncărcare) ```  **De ce SPA-urile se simt mult mai bine:** - Doar părțile care s-au schimbat de fapt sunt actualizate (inteligent, nu?) - Fără întreruperi deranjante - utilizatorii rămân în fluxul lor - Mai puține date călătorind în rețea înseamnă încărcare mai rapidă - Totul se simte rapid și receptiv, ca aplicațiile de pe telefonul tău ### Evoluția către API-ul Modern Fetch Browserele moderne oferă [`Fetch` API](https://developer.mozilla.org/docs/Web/API/Fetch_API), care înlocuiește vechiul [`XMLHttpRequest`](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest). Ca diferența dintre a opera un telegraf și a folosi email-ul, Fetch API folosește promisiuni pentru un cod asincron mai curat și gestionează JSON-ul în mod natural. | Caracteristică | XMLHttpRequest | Fetch API | |---------|----------------|----------| | **Sintaxă** | Bazată pe callback-uri complexe | Curată, bazată pe promisiuni | | **Gestionarea JSON** | Necesită parsare manuală | Metodă `.json()` integrată | | **Gestionarea erorilor** | Informații limitate despre erori | Detalii complete despre erori | | **Compatibilitate modernă** | Compatibilitate legacy | Promisiuni ES6+ și async/await | > 💡 **Compatibilitatea browserelor**: Vești bune - Fetch API funcționează în toate browserele moderne! Dacă ești curios despre versiuni specifice, [caniuse.com](https://caniuse.com/fetch) are povestea completă a compatibilității. > **Pe scurt:** - Funcționează excelent în Chrome, Firefox, Safari și Edge (practic oriunde se află utilizatorii tăi) - Doar Internet Explorer are nevoie de ajutor suplimentar (și sincer, e timpul să îl lași în urmă) - Te pregătește perfect pentru elegantele modele async/await pe care le vom folosi mai târziu ### Implementarea Login-ului și Preluarea Datelor Acum să implementăm sistemul de autentificare care transformă aplicația ta bancară dintr-un afișaj static într-o aplicație funcțională. Ca protocoalele de autentificare folosite în facilități militare sigure, vom verifica credențialele utilizatorului și apoi vom oferi acces la datele specifice ale acestuia. Vom construi acest sistem incremental, începând cu autentificarea de bază și apoi adăugând capabilitățile de preluare a datelor. #### Pasul 1: Creează Baza Funcției de Login Deschide fișierul `app.js` și adaugă o nouă funcție `login`. Aceasta va gestiona procesul de autentificare a utilizatorului: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; } ``` **Să descompunem acest cod:** - Cuvântul cheie `async`? Indică JavaScript-ului „hei, această funcție s-ar putea să aștepte niște lucruri” - Luăm formularul de pe pagină (nimic complicat, doar îl găsim după ID) - Extragem ceea ce a introdus utilizatorul ca nume de utilizator - Un truc util: poți accesa orice câmp de formular după atributul său `name` - fără apeluri suplimentare getElementById! > 💡 **Model de acces la Formular**: Fiecare control al formularului poate fi accesat prin numele său (setat în HTML folosind atributul `name`) ca o proprietate a elementului formular. Acesta oferă o modalitate curată și lizibilă de a obține datele formularului. #### Pasul 2: Creează Funcția pentru Preluarea Datelor Contului Apoi, vom crea o funcție dedicată pentru a prelua datele contului de la server. Aceasta urmează același model ca funcția ta de înregistrare, dar se concentrează pe preluarea datelor: ```javascript async function getAccount(user) { try { const response = await fetch('//localhost:5000/api/accounts/' + encodeURIComponent(user)); return await response.json(); } catch (error) { return { error: error.message || 'Unknown error' }; } } ``` **Ce face acest cod:** - **Folosește** API-ul modern `fetch` pentru a cere date asincron - **Construiește** un URL pentru o cerere GET cu parametrul numelui de utilizator - **Aplică** `encodeURIComponent()` pentru a trata în siguranță caractere speciale din URL - **Convertește** răspunsul în format JSON pentru manipulare ușoară - **Gestionează** erorile într-un mod grațios, întorcând un obiect eroare în loc să se prăbușească > ⚠️ **Notă de securitate**: Funcția `encodeURIComponent()` gestionează caracterele speciale din URL-uri. Ca sistemele de codare folosite în comunicațiile navale, se asigură că mesajul tău ajunge exact așa cum l-ai trimis, prevenind interpretarea greșită a caracterelor precum "#" sau "&". > **De ce contează asta:** - Previne problemele cauzate de caractere speciale în URL-uri - Protejează împotriva atacurilor de manipulare URL - Asigură că serverul primește datele așa cum trebuie - Urmează practici de codare securizate #### Înțelegerea Cererilor HTTP GET Iată ceva ce te-ar putea surprinde: când folosești `fetch` fără opțiuni suplimentare, acesta creează automat o cerere [`GET`](https://developer.mozilla.org/docs/Web/HTTP/Methods/GET). Acest lucru este perfect pentru ceea ce facem noi – cerem serverului „hei, pot vedea datele contului acestui utilizator?” Gândește-te la cererile GET ca la a cere politicos să împrumuți o carte de la bibliotecă - ceri să vezi ceva ce există deja. Cererile POST (pe care le-am folosit la înregistrare) sunt mai mult ca a trimite o carte nouă pentru a fi adăugată în colecție. | Cerere GET | Cerere POST | |-------------|-------------| | **Scop** | Preluare date existente | Trimitere date noi către server | | **Parametri** | În URL (cale/șir de interogare) | În corpul cererii | | **Caching** | Poate fi cached de browsere | De obicei nu este cached | | **Securitate** | Vizibil în URL/jurnale | Ascuns în corpul cererii | ```mermaid sequenceDiagram participant B as Browser participant S as Server Note over B,S: Cerere GET (Preluare Date) B->>S: GET /api/accounts/test S-->>B: 200 OK + Date Cont Note over B,S: Cerere POST (Trimitere Date) B->>S: POST /api/accounts + Date Cont Nou S-->>B: 201 Creat + Confirmare Note over B,S: Gestionare Eroare B->>S: GET /api/accounts/nonexistent S-->>B: 404 Neprezent + Mesaj Eroare ``` #### Pasul 3: Asamblarea Întregului Proces Acum partea satisfăcătoare - să conectăm funcția de preluare a contului cu procesul de login. Aici totul se leagă: ```javascript async function login() { const loginForm = document.getElementById('loginForm'); const user = loginForm.user.value; const data = await getAccount(user); if (data.error) { return console.log('loginError', data.error); } account = data; navigate('/dashboard'); } ``` Această funcție urmează o secvență clară: - Extrage numele de utilizator din input-ul formularului - Cere datele contului acestui utilizator de la server - Gestionează eventualele erori - Stochează datele contului și navighează către dashboard la succes > 🎯 **Model Async/Await**: Deoarece `getAccount` este o funcție asincronă, folosim cuvântul cheie `await` pentru a opri execuția până când serverul răspunde. Astfel prevenim continuarea codului cu date nedefinite. #### Pasul 4: Creează un Loc pentru Datele Tale Aplicația ta are nevoie de un loc unde să păstreze informațiile contului odată ce sunt încărcate. Gândește-te la asta ca la memoria pe termen scurt a aplicației – un loc unde să ții datele utilizatorului curent la îndemână. Adaugă această linie în partea de sus a fișierului `app.js`: ```javascript // Acesta conține datele contului utilizatorului curent let account = null; ``` **De ce avem nevoie de asta:** - Menține datele contului accesibile din orice parte a aplicației - Pornind de la `null` înseamnă „nimeni nu este logat încă” - Se actualizează când cineva se loghează sau se înregistrează cu succes - Acționează ca o sursă unică de adevăr - fără confuzie cine este logat #### Pasul 5: Leagă Formularul Tău Acum să conectăm funcția ta nouă de login la formularul HTML. Actualizează tag-ul formular astfel: ```html
``` **Ce face această mică schimbare:** - Oprește formularul să facă comportamentul lui implicit de „reîncărcare a întregii pagini” - Apelează funcția ta personalizată JavaScript în loc - Menține totul fluid și cu aspectul unei aplicații single-page - Îți oferă controlul complet asupra a ceea ce se întâmplă când utilizatorii apasă „Login” #### Pasul 6: Îmbunătățește Funcția ta de Înregistrare Pentru consistență, actualizează funcția `register` să salveze și ea datele contului și să navigheze către dashboard: ```javascript // Adaugă aceste linii la sfârșitul funcției tale de înregistrare account = result; navigate('/dashboard'); ``` **Această îmbunătățire oferă:** - **Tranziție lină** de la înregistrare la dashboard - **Experiență consistentă** pentru utilizatori între fluxurile de login și înregistrare - **Acces imediat** la datele contului după înregistrare reușită #### Testarea Implementării Tale ```mermaid flowchart TD A[Utilizator introduce datele de autentificare] --> B[Funcția de autentificare apelată] B --> C[Preia datele contului de pe server] C --> D{Date primite cu succes?} D -->|Da| E[Stochează datele contului global] D -->|Nu| F[Afișează mesaj de eroare] E --> G[Navighează către tabloul de bord] F --> H[Utilizatorul rămâne pe pagina de autentificare] ``` **E timpul să testezi implementarea:** 1. Creează un cont nou pentru a verifica dacă totul funcționează 2. Încearcă să te loghezi cu aceleași credențiale 3. Aruncă o privire în consola browserului (F12) dacă ceva pare în neregulă 4. Asigură-te că ajungi pe dashboard după un login reușit Dacă ceva nu funcționează, nu intra în panică! Majoritatea problemelor sunt corectări simple, cum ar fi greșeli de scriere sau uitarea de a porni serverul API. #### Un Cuvânt Rapid Despre Magia Cross-Origin Te-ai putea întreba: „Cum conversa aplicația mea web cu acest server API dacă rulează pe porturi diferite?” Bună întrebare! Aceasta atinge un aspect cu care orice dezvoltator web se confruntă la un moment dat. > 🔒 **Securitate Cross-Origin**: Browserele aplică o „politică de același origini” pentru a preveni comunicările neautorizate între domenii diferite. Ca un sistem de control la Pentagon, ele verifică dacă comunicarea este autorizată înainte de a permite transferul de date. > **În configurația noastră:** - Aplicația web rulează pe `localhost:3000` (server de dezvoltare) - Serverul API rulează pe `localhost:5000` (server backend) - Serverul API include [anteturile CORS](https://developer.mozilla.org/docs/Web/HTTP/CORS) care autorizează explicit comunicarea din partea aplicației web Această configurație reflectă dezvoltarea reală unde aplicațiile frontend și backend rulează de obicei pe servere separate. > 📚 **Află mai multe**: Explorează mai profund API-urile și preluarea datelor cu acest modul complet [Microsoft Learn despre API-uri](https://docs.microsoft.com/learn/modules/use-apis-discover-museum-art/?WT.mc_id=academic-77807-sagibbon). ## Transformă Datele în Viață în HTML Acum vom face datele preluate vizibile utilizatorilor prin manipularea DOM-ului. Ca procesul de dezvoltare a fotografiilor într-o cameră obscură, luăm date invizibile și le redăm într-un format pe care utilizatorii îl pot vedea și cu care pot interacționa. Manipularea DOM este tehnica care transformă paginile web statice în aplicații dinamice care își actualizează conținutul în funcție de interacțiunile utilizatorilor și răspunsurile serverului. ### Alegerea Uneltei Potrivite pentru Fiecare Sarcină Când vine vorba de actualizarea HTML-ului cu JavaScript, ai mai multe opțiuni. Gândește-le ca pe diferite unelte dintr-o cutie de scule - fiecare perfectă pentru anumite joburi: | Metodă | Pentru ce este excelentă | Când să o folosești | Nivel de siguranță | |--------|-------------------------|--------------------|--------------------| | `textContent` | Afișarea sigură a datelor utilizatorului | Oricând afișezi text | ✅ Foarte sigur | | `createElement()` + `append()` | Construirea de layout-uri complexe | Crearea de secțiuni/listări noi | ✅ Impecabil | | `innerHTML` | Setarea conținutului HTML | ⚠️ Încearcă să eviți aceasta | ❌ Riscuri mari | #### Modalitatea Sigură de a Afișa Text: textContent Proprietatea [`textContent`](https://developer.mozilla.org/docs/Web/API/Node/textContent) este cea mai bună prietenă când afișezi date provenite de la utilizatori. E ca un portar la intrarea în pagina ta web - nu lasă să treacă nimic periculos: ```javascript // Mod sigur și fiabil de a actualiza textul const balanceElement = document.getElementById('balance'); balanceElement.textContent = account.balance; ``` **Beneficiile textContent:** - Tratează totul ca text simplu (previne executarea scripturilor) - Șterge automat conținutul existent - Eficient pentru actualizări simple de text - Oferă securitate încorporată împotriva conținutului rău intenționat #### Crearea Elementelor HTML Dinamice Pentru conținut mai complex, combină [`document.createElement()`](https://developer.mozilla.org/docs/Web/API/Document/createElement) cu metoda [`append()`](https://developer.mozilla.org/docs/Web/API/ParentNode/append): ```javascript // Mod sigur de a crea elemente noi const transactionItem = document.createElement('div'); transactionItem.className = 'transaction-item'; transactionItem.textContent = `${transaction.date}: ${transaction.description}`; container.append(transactionItem); ``` **Cum funcționează această abordare:** - **Creează** elemente DOM noi programatic - **Păstrează** control complet asupra atributelor și conținutului elementelor - **Permite** structuri complexe și imbricate de elemente - **Asigură** securitate prin separarea structurii de conținut > ⚠️ **Considerații de Securitate**: Deși [`innerHTML`](https://developer.mozilla.org/docs/Web/API/Element/innerHTML) apare în multe tutoriale, poate executa scripturi încorporate. La fel ca protocoalele de securitate CERN care previn execuția neautorizată de cod, folosirea `textContent` și `createElement` oferă alternative mai sigure. > **Riscurile innerHTML:** - Execută orice tag `