fix api
This commit is contained in:
@@ -10,18 +10,8 @@ const btnFetch = document.querySelector('#btnFetch');
|
|||||||
* FUNZIONE: Crea utente card
|
* FUNZIONE: Crea utente card
|
||||||
*
|
*
|
||||||
* Crea la card completa dell'utente e la inserisce nell'elemento result
|
* Crea la card completa dell'utente e la inserisce nell'elemento result
|
||||||
|
* La struttura dell'oggetto user è visibile nella documentazione API.
|
||||||
* Funzione già fatta - non modificare
|
* Funzione già fatta - non modificare
|
||||||
* L'oggetto user ha questa struttura:
|
|
||||||
* {
|
|
||||||
* id: number,
|
|
||||||
* nome: string,
|
|
||||||
* cognome: string,
|
|
||||||
* email: string,
|
|
||||||
* avatar: string (url),
|
|
||||||
* dataNascita: string (formato YYYY-MM-DD),
|
|
||||||
* comune: string,
|
|
||||||
* attivo: boolean
|
|
||||||
* }
|
|
||||||
*/
|
*/
|
||||||
function creaCardUtente(user) {
|
function creaCardUtente(user) {
|
||||||
result.innerHTML = `
|
result.innerHTML = `
|
||||||
@@ -58,12 +48,12 @@ function creaCardUtente(user) {
|
|||||||
* e logga l'errore in console (per debug)
|
* e logga l'errore in console (per debug)
|
||||||
* Funzione già fatta - non modificare
|
* Funzione già fatta - non modificare
|
||||||
*/
|
*/
|
||||||
function handleError(message) {
|
function mostraErrore(message) {
|
||||||
console.error('Errore:', message);
|
console.error('Errore:', message);
|
||||||
result.innerHTML = `
|
result.innerHTML = `
|
||||||
<div class="error">
|
<div class="error">
|
||||||
<strong>❌ ${message}</strong>
|
<strong>❌ ${message}</strong>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,20 +66,21 @@ function handleError(message) {
|
|||||||
* fare una chiamata GET a BASE_URL + "/users/" + id e mostrare i dati
|
* fare una chiamata GET a BASE_URL + "/users/" + id e mostrare i dati
|
||||||
*
|
*
|
||||||
* Passi:
|
* Passi:
|
||||||
* 1. Leggi l'ID utente dall'input
|
* 1. Leggi l'ID utente dall'input
|
||||||
* 2. Controlla che l'ID sia valido, ovvero un numero tra 1 e 40
|
* 2. Controlla che l'ID sia valido, ovvero un numero tra 1 e 40
|
||||||
* In caso contrario, mostra un messaggio di errore (usa handleError()) e return
|
* In caso contrario, mostra un messaggio di errore (usa handleError()) e return
|
||||||
* 3. Mostra lo spinner di caricamento (rimuovi la classe nascosto)
|
* 3. Mostra lo spinner di caricamento (rimuovi la classe nascosto)
|
||||||
* 4. Apri un blocco try/catch
|
* 4. Apri un blocco try/catch
|
||||||
* 5. Fai una fetch GET a /users/{id}
|
* 5. Fai una fetch GET a /users/{id}
|
||||||
* 6. Se la risposta non è OK, usa handleError() per mostrare un messaggio e return
|
* 6. Se la risposta non è OK, lancia un errore con un messaggio che includa lo status code
|
||||||
* 7. Converti la risposta in JSON
|
* 7. Converti la risposta in JSON
|
||||||
* 8. Mostra i dati dell'utente chiamando creaCardUtente(user)
|
* 8. Mostra i dati dell'utente chiamando creaCardUtente(user)
|
||||||
* 9. Nascondi lo spinner di caricamento (aggiungi la classe nascosto)
|
* 9. Nel catch, mostra un messaggio di errore usando handleError() e logga l'errore in console
|
||||||
|
* 10. Nascondi lo spinner di caricamento (aggiungi la classe nascosto)
|
||||||
*/
|
*/
|
||||||
async function fetchUser() {
|
async function fetchUser() {
|
||||||
// TODO Rimuovi questa riga e completa la funzione
|
// TODO Rimuovi questa riga e completa la funzione
|
||||||
handleError('Codice non implementato - Completa la funzione fetchUser()');
|
mostraErrore('Codice non implementato - Completa la funzione fetchUser()');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,23 +5,47 @@ const counter = document.querySelector('#counter');
|
|||||||
const result = document.querySelector('#result');
|
const result = document.querySelector('#result');
|
||||||
const btnFetch = document.querySelector('#btnLoadUsers');
|
const btnFetch = document.querySelector('#btnLoadUsers');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visualizza gli utenti in una griglia di card
|
||||||
|
* Funzione già fatta - non modificare
|
||||||
|
*/
|
||||||
|
function creaListaUtenti(users) {
|
||||||
|
if (!Array.isArray(users) || users.length === 0) {
|
||||||
|
mostraErrore('Nessun utente trovato');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CREA CARD PER OGNI UTENTE
|
||||||
|
const cardsHTML = users.map(user => creaCardUtente(user)).join('');
|
||||||
|
result.innerHTML = cardsHTML;
|
||||||
|
|
||||||
|
// MOSTRA CONTATORE
|
||||||
|
counter.innerHTML = `📊 Totale: <strong>${users.length} utenti</strong>`;
|
||||||
|
counter.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FUNZIONE che crea la card HTML per un singolo utente
|
* FUNZIONE che crea la stringa con la struttura HTML della card per un singolo utente
|
||||||
|
* Questa viene restituita a creaListaUtenti() per ogni utente e poi inserita nel DOM
|
||||||
|
* La struttura dell'oggetto user è visibile nella documentazione API.
|
||||||
*
|
*
|
||||||
* Passi:
|
* Passi:
|
||||||
* 1. Crea un template literal con la struttura HTML della card
|
* 1. Crea un template literal con la struttura HTML della card
|
||||||
* 2. Usa i dati dell'oggetto user per popolare i campi
|
* La struttura della card deve essere simile a questa:
|
||||||
* 3. La struttura della card deve essere simile a questa:
|
|
||||||
* <div class="user-card">
|
<div class="user-card">
|
||||||
* <img src="avatar_url" alt="Avatar" class="card-avatar">
|
<img src="avatar_url" alt="Avatar" class="card-avatar">
|
||||||
* <div class="card-content">
|
<div class="card-content">
|
||||||
* <h3>Nome Cognome</h3>
|
<h3>Nome Cognome</h3>
|
||||||
* <p class="email">📧 email</p>
|
<p class="email">📧 email</p>
|
||||||
* <p class="location">📍 comune</p>
|
<p class="location">📍 comune</p>
|
||||||
* <div class="status attivo/inattivo"> Attivo/Inattivo </div>
|
<div class="status attivo/inattivo"> Attivo/Inattivo </div>
|
||||||
* </div>
|
</div>
|
||||||
* </div>
|
</div>
|
||||||
|
|
||||||
|
* 2. Sostituisci i valori con quelli dell'oggetto user passato come parametro:
|
||||||
|
* 3. Restituisci la stringa creata
|
||||||
*/
|
*/
|
||||||
function creaCardUtente(user) {
|
function creaCardUtente(user) {
|
||||||
return ``;
|
return ``;
|
||||||
@@ -35,18 +59,13 @@ function creaCardUtente(user) {
|
|||||||
* e logga l'errore in console (per debug)
|
* e logga l'errore in console (per debug)
|
||||||
* Funzione già fatta - non modificare
|
* Funzione già fatta - non modificare
|
||||||
*/
|
*/
|
||||||
function handleError(message) {
|
function mostraErrore(message) {
|
||||||
result.innerHTML = '';
|
|
||||||
|
|
||||||
let div = document.createElement('div');
|
|
||||||
div.className = 'error';
|
|
||||||
|
|
||||||
let strong = document.createElement('strong');
|
|
||||||
strong.textContent = `❌ ${message}`;
|
|
||||||
|
|
||||||
div.appendChild(strong);
|
|
||||||
result.appendChild(div);
|
|
||||||
console.error('Errore:', message);
|
console.error('Errore:', message);
|
||||||
|
result.innerHTML = `
|
||||||
|
<div class="error">
|
||||||
|
<strong>❌ ${message}</strong>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -57,35 +76,17 @@ function handleError(message) {
|
|||||||
* 1. Mostra lo spinner di caricamento (rimuovi la classe nascosto)
|
* 1. Mostra lo spinner di caricamento (rimuovi la classe nascosto)
|
||||||
* 2. Apri un blocco try/catch
|
* 2. Apri un blocco try/catch
|
||||||
* 3. Fai una fetch GET a /users
|
* 3. Fai una fetch GET a /users
|
||||||
* 4. Se la risposta non è OK, usa handleError() per mostrare un messaggio e return
|
* 4. Se la risposta non è OK lancia un errore con un messaggio che includa lo status code
|
||||||
* 5. Converti la risposta da stringa JSON a oggetto JavaScript
|
* 5. Converti la risposta da stringa JSON a oggetto JavaScript
|
||||||
* 6. Mostra i dati degli utenti chiamando mostraUtenti(users)
|
* 6. Mostra i dati degli utenti chiamando creaListaUtenti(users)
|
||||||
* 7. Nascondi lo spinner di caricamento (aggiungi la classe nascosto)
|
* 7. Nel catch, mostra un messaggio di errore usando mostraErrore()
|
||||||
|
* 8. Nascondi lo spinner di caricamento (aggiungi la classe nascosto)
|
||||||
*/
|
*/
|
||||||
async function fetchAllUsers() {
|
async function fetchAllUsers() {
|
||||||
// TODO Rimuovi questa riga e completa la funzione
|
// TODO Rimuovi questa riga e completa la funzione
|
||||||
handleError('Codice non implementato - Completa la funzione fetchAllUsers()');
|
mostraErrore('Codice non implementato - Completa la funzione fetchAllUsers()');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Visualizza gli utenti in una griglia di card
|
|
||||||
* Funzione già fatta - non modificare
|
|
||||||
*/
|
|
||||||
function mostraUtenti(users) {
|
|
||||||
if (!Array.isArray(users) || users.length === 0) {
|
|
||||||
handleError('Nessun utente trovato');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// CREA CARD PER OGNI UTENTE
|
|
||||||
const cardsHTML = users.map(user => creaCardUtente(user)).join('');
|
|
||||||
result.innerHTML = cardsHTML;
|
|
||||||
|
|
||||||
// MOSTRA CONTATORE
|
|
||||||
counter.innerHTML = `📊 Totale: <strong>${users.length} utenti</strong>`;
|
|
||||||
counter.style.display = 'block';
|
|
||||||
}
|
|
||||||
|
|
||||||
// COLLEGA IL BOTTONE
|
// COLLEGA IL BOTTONE
|
||||||
btnFetch.addEventListener('click', fetchAllUsers);
|
btnFetch.addEventListener('click', fetchAllUsers);
|
||||||
|
|||||||
@@ -1,27 +1,18 @@
|
|||||||
// ⚠️ COMPILARE E CONTROLLARE PRIMA DI INIZIARE ⚠️
|
// ⚠️ COMPILARE E CONTROLLARE PRIMA DI INIZIARE ⚠️
|
||||||
const BASE_URL = 'http://localhost:5000/api';
|
const BASE_URL = 'http://localhost:5000/api';
|
||||||
const userId = document.getElementById('userId');
|
const userId = document.querySelector('#userId');
|
||||||
const loading = document.getElementById('loading');
|
const loading = document.querySelector('#loading');
|
||||||
const userProfile = document.getElementById('userProfile');
|
const userProfile = document.querySelector('#userProfile');
|
||||||
const postsContainer = document.getElementById('postsContainer');
|
const postsContainer = document.querySelector('#postsContainer');
|
||||||
const btnFetch = document.getElementById('btnFetch');
|
const btnFetch = document.querySelector('#btnFetch');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FUNZIONE: Crea un utente card
|
* FUNZIONE: Crea un utente card
|
||||||
*
|
*
|
||||||
* Crea la card completa dell'utente e la inserisce nell'elemento userProfile
|
* Crea la card completa dell'utente e la inserisce nell'elemento userProfile
|
||||||
* L'oggetto user ha questa struttura:
|
* La struttura dell'oggetto user è visibile nella documentazione API.
|
||||||
* {
|
* Funzione già fatta - non modificare
|
||||||
* id: number,
|
|
||||||
* nome: string,
|
|
||||||
* cognome: string,
|
|
||||||
* email: string,
|
|
||||||
* avatar: string (url),
|
|
||||||
* dataNascita: string (formato YYYY-MM-DD),
|
|
||||||
* comune: string,
|
|
||||||
* attivo: boolean
|
|
||||||
* }
|
|
||||||
*/
|
*/
|
||||||
function creaCardUtente(user) {
|
function creaCardUtente(user) {
|
||||||
userProfile.innerHTML = `
|
userProfile.innerHTML = `
|
||||||
@@ -90,13 +81,13 @@ function creaCardPosts(postList) {
|
|||||||
*
|
*
|
||||||
* Mostra un messaggio di errore e logga in console
|
* Mostra un messaggio di errore e logga in console
|
||||||
*/
|
*/
|
||||||
function handleError(message) {
|
function mostraErrore(message) {
|
||||||
|
console.error('Errore:', message);
|
||||||
userProfile.innerHTML = `
|
userProfile.innerHTML = `
|
||||||
<div class="error">
|
<div class="error">
|
||||||
<strong>❌ ${message}</strong>
|
<strong>❌ ${message}</strong>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
console.error('Errore:', message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -110,15 +101,16 @@ function handleError(message) {
|
|||||||
* 4. Apri un blocco try/catch
|
* 4. Apri un blocco try/catch
|
||||||
* 5. Fai DUE fetch:
|
* 5. Fai DUE fetch:
|
||||||
* - GET /users/{id}
|
* - GET /users/{id}
|
||||||
* - GET /posts
|
* - GET /posts?userId={id}
|
||||||
* 6. Filtra i post per trovare solo quelli di questo utente (usando userId)
|
* Nota che il secondo endpoint è un filtro: ti restituirà solo i post di quell'utente
|
||||||
* - Il filtro va fatto in JS, ma puoi anche usare un endpoint come /posts?userId={id}
|
* 6. Se una delle due risposte non è OK, lancia un errore con un messaggio che includa lo status code
|
||||||
* 7. Mostra i risultati chiamando prima creaCardUtente(user) e poi creaCardPosts(posts)
|
* 7. Mostra i risultati chiamando prima creaCardUtente(user) e poi creaCardPosts(posts)
|
||||||
* 8. Gestisci gli errori con handleError()
|
* 8. Nel catch, mostra un messaggio di errore usando mostraErrore()
|
||||||
|
* 9. Alla fine, nascondi lo spinner di caricamento
|
||||||
*/
|
*/
|
||||||
async function fetchUserAndPosts() {
|
async function fetchUserAndPosts() {
|
||||||
// TODO Rimuovi questa riga e completa la funzione
|
// TODO Rimuovi questa riga e completa la funzione
|
||||||
handleError('Codice non implementato - Completa la funzione fetchUserAndPosts()');
|
mostraErrore('Codice non implementato - Completa la funzione fetchUserAndPosts()');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ const btnSearch = document.querySelector('#btnSearch');
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* FUNZIONE: Crea la card HTML per un singolo post con autore a fianco
|
* FUNZIONE: Crea la card HTML per un singolo post con autore a fianco
|
||||||
|
* Prende un oggetto post e un oggetto autore e crea una card da inserire nei risultati
|
||||||
|
* La struttura dell'oggetto post è visibile nella documentazione API.
|
||||||
|
* La struttura dell'oggetto autore è visibile nella documentazione API.
|
||||||
*
|
*
|
||||||
* Funzione già fatta - non modificare
|
* Funzione già fatta - non modificare
|
||||||
*/
|
*/
|
||||||
@@ -40,13 +43,13 @@ function creaElementoPost(post, autore) {
|
|||||||
* Mostra un messaggio di errore e logga in console
|
* Mostra un messaggio di errore e logga in console
|
||||||
* Funzione già fatta - non modificare
|
* Funzione già fatta - non modificare
|
||||||
*/
|
*/
|
||||||
function handleError(message) {
|
function mostraErrore(message) {
|
||||||
|
console.error('Errore:', message);
|
||||||
results.innerHTML = `
|
results.innerHTML = `
|
||||||
<div class="error">
|
<div class="error">
|
||||||
<strong>❌ ${message}</strong>
|
<strong>❌ ${message}</strong>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
console.error('Errore:', message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -55,18 +58,18 @@ function handleError(message) {
|
|||||||
*
|
*
|
||||||
* Devi completare questa funzione:
|
* Devi completare questa funzione:
|
||||||
* 1. Leggi la parola chiave dall'input
|
* 1. Leggi la parola chiave dall'input
|
||||||
* 2. Svuota il contenuto dei risultati (results.innerHTML = '')
|
* 2. Valida che non sia vuota (usa trim)
|
||||||
* 3. Valida che non sia vuota (usa trim)
|
* 3. Svuota il contenuto dei risultati (results.innerHTML = '')
|
||||||
* 4. Mostra lo spinner di caricamento
|
* 4. Mostra lo spinner di caricamento
|
||||||
* 5. Apri un blocco try/catch
|
* 5. Apri un blocco try/catch
|
||||||
* 6. Fai una GET a /posts
|
* 6. Fai una GET a /posts
|
||||||
* 7. Filtra i post dove titolo O contenuto contiene la keyword
|
* 7. Filtra i post dove titolo contiene la keyword
|
||||||
* (ricorda minuscole per la ricerca)
|
* (ricorda minuscole per la ricerca in entrambe le stringhe)
|
||||||
* 8. Se nessun post trovato, usa handleError() e return
|
* 8. Se nessun post trovato lancia un errore "Nessun post trovato"
|
||||||
* 9. Per ogni post trovato:
|
* 9. Per ogni post trovato:
|
||||||
* - Prendi l'id autore e fai una GET a /users?id=[id]
|
* - Prendi l'id autore e fai una GET a /users?id=[id]
|
||||||
* - Crea un nuovo elemento della lista dei risultati con creaElementoPost(post, autore)
|
* - Crea un nuovo elemento della lista dei risultati con creaElementoPost(post, autore)
|
||||||
* 10. Gestisci gli errori con handleError()
|
* 10. Nel catch, mostra un messaggio di errore usando mostraErrore()
|
||||||
* 11. Nascondi lo spinner di caricamento
|
* 11. Nascondi lo spinner di caricamento
|
||||||
*/
|
*/
|
||||||
async function fetchPostsByKeyword() {
|
async function fetchPostsByKeyword() {
|
||||||
|
|||||||
@@ -13,12 +13,36 @@ const loading = document.querySelector('#loading');
|
|||||||
const counter = document.querySelector('#counter');
|
const counter = document.querySelector('#counter');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FUNZIONE: Crea la card HTML per tutti i TODO passati come parametro
|
* FUNZIONE: Visualizza i TODO nella pagina
|
||||||
|
*
|
||||||
|
* Prende in input un array di oggetti TODO (con struttura visibile nella documentazione API)
|
||||||
|
* e crea la lista dei TODO all'interno dell'elemento todosContainer.
|
||||||
|
* Ogni TODO mostra titolo, ID, e uno checkbox per completarlo.
|
||||||
|
* Se l'array è vuoto, mostra un messaggio "Nessun TODO. Creane uno!".
|
||||||
|
* Funzione già fatta - non modificare
|
||||||
*/
|
*/
|
||||||
function creaCardsTodos(todoList) {
|
function creaListaTodos(todos) {
|
||||||
allTodos = todoList.map((todo) => `
|
|
||||||
|
if (!Array.isArray(todos) || todos.length === 0) {
|
||||||
|
todosContainer.innerHTML = '<div class="empty">Nessun TODO. Creane uno!</div>';
|
||||||
|
counter.classList.add('nascosto');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CONTA COMPLETATI E NON
|
||||||
|
const completed = todos.filter(t => t.completato).length;
|
||||||
|
const pending = todos.length - completed;
|
||||||
|
|
||||||
|
// MOSTRA COUNTER
|
||||||
|
counter.innerHTML = `
|
||||||
|
📊 Totale: <strong>${todos.length}</strong> |
|
||||||
|
✅ Completati: <strong>${completed}</strong> |
|
||||||
|
⏳ In Sospeso: <strong>${pending}</strong>
|
||||||
|
`;
|
||||||
|
counter.classList.remove('nascosto');
|
||||||
|
|
||||||
|
todosContainer.innerHTML = todos.map((todo) => `
|
||||||
<div class="todo-item ${todo.completato ? 'completed' : ''}">
|
<div class="todo-item ${todo.completato ? 'completed' : ''}">
|
||||||
<div class="todo-checkbox">
|
<div class="todo-checkbox">
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
@@ -32,24 +56,21 @@ function creaCardsTodos(todoList) {
|
|||||||
<button class="btn-delete" onclick="deleteTodo(${todo.id})">🗑️ Elimina</button>
|
<button class="btn-delete" onclick="deleteTodo(${todo.id})">🗑️ Elimina</button>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
|
|
||||||
todosContainer.innerHTML = allTodos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FUNZIONE: Gestione errori
|
* FUNZIONE: Gestione errori
|
||||||
*
|
*
|
||||||
* Mostra un messaggio di errore e logga in console
|
* Mostra un messaggio di errore e logga in console
|
||||||
*/
|
*/
|
||||||
function handleError(message) {
|
function mostraErrore(message) {
|
||||||
|
console.error('Errore:', message);
|
||||||
todosContainer.innerHTML = `
|
todosContainer.innerHTML = `
|
||||||
<div class="error">
|
<div class="error">
|
||||||
<strong>❌ ${message}</strong>
|
<strong>❌ ${message}</strong>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
console.error('Errore:', message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -57,10 +78,10 @@ function handleError(message) {
|
|||||||
* ESERCIZIO 4: Todo App CRUD Completa
|
* ESERCIZIO 4: Todo App CRUD Completa
|
||||||
*
|
*
|
||||||
* Devi implementare 4 funzioni:
|
* Devi implementare 4 funzioni:
|
||||||
* 1. fetchTodosUtente() - GET /todos?userId={id} (READ)
|
* 1. fetchTodosUtente() - GET /todos?userId={id} (READ)
|
||||||
* 2. addTodo() - POST /todos (CREATE)
|
* 2. addTodo() - POST /todos (CREATE)
|
||||||
* 3. toggleTodo() - PUT /todos/{id} (UPDATE)
|
* 3. toggleTodo() - PUT /todos/{id} (UPDATE)
|
||||||
* 4. deleteTodo() - DELETE /todos/{id} (DELETE)
|
* 4. deleteTodo() - DELETE /todos/{id} (DELETE)
|
||||||
*
|
*
|
||||||
* BONUS (OPZIONALE): Persistenza con localStorage
|
* BONUS (OPZIONALE): Persistenza con localStorage
|
||||||
* Se hai completato tutte le funzioni, puoi aggiungere la persistenza dell'utente:
|
* Se hai completato tutte le funzioni, puoi aggiungere la persistenza dell'utente:
|
||||||
@@ -82,15 +103,16 @@ let currentUserId = null; // Variabile globale per tenere traccia dell'ID utente
|
|||||||
* 3. Mostra lo spinner di caricamento
|
* 3. Mostra lo spinner di caricamento
|
||||||
* 4. Apri un blocco try/catch
|
* 4. Apri un blocco try/catch
|
||||||
* 5. Fai una GET a /todos?userId={id}
|
* 5. Fai una GET a /todos?userId={id}
|
||||||
* 6. Se non OK, mostra errore e return
|
* 6. Se non OK, lancia un errore con messaggio che include lo status code
|
||||||
* 7. Converti la risposta in JSON
|
* 7. Converti la risposta in JSON
|
||||||
* 8. Chiama displayTodos() per visualizzare
|
* 8. Chiama displayTodos() per visualizzare
|
||||||
* 9. Nascondi lo spinner e mostra addTodoSection
|
* 9. Nel catch, mostra un messaggio di errore
|
||||||
* 10. Salva l'ID utente in currentUserId
|
* 10. Nascondi lo spinner e mostra addTodoSection
|
||||||
|
* 11. Salva l'ID utente nella variabile globale currentUserId
|
||||||
*/
|
*/
|
||||||
async function fetchTodosUtente() {
|
async function fetchTodosUtente() {
|
||||||
// TODO Rimuovi questa riga e completa la funzione
|
// TODO Rimuovi questa riga e completa la funzione
|
||||||
handleError('Codice non implementato - Completa la funzione fetchTodosUtente()');
|
mostraErrore('Codice non implementato - Completa la funzione fetchTodosUtente()');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -98,16 +120,17 @@ async function fetchTodosUtente() {
|
|||||||
* FUNZIONE 2️⃣: Aggiungi TODO (POST)
|
* FUNZIONE 2️⃣: Aggiungi TODO (POST)
|
||||||
*
|
*
|
||||||
* Passi:
|
* Passi:
|
||||||
* 1. Verifica che un utente sia stato caricato (currentUserId !== null)
|
* 1. Verifica che un utente sia stato caricato (currentUserId !== null)
|
||||||
* Altrimenti, mostra errore "Carica prima un utente!" e return
|
* Altrimenti, mostra errore "Carica prima un utente!" e return
|
||||||
* 2. Leggi il testo dal campo di input del nuovo TODO
|
* 2. Leggi il testo dal campo di input del nuovo TODO
|
||||||
* 3. Valida con trim che non sia vuoto
|
* 3. Valida con trim che non sia vuoto
|
||||||
* 4. Mostra lo spinner di caricamento
|
* 4. Mostra lo spinner di caricamento
|
||||||
* 5. Apri un blocco try/catch
|
* 5. Apri un blocco try/catch
|
||||||
* 6. Fai una POST a /todos con body: {userId, titolo, completato: false}
|
* 6. Fai una POST a /todos con body: {userId, titolo, completato: false}
|
||||||
* 7. Se non OK, mostra errore
|
* 7. Se non OK, lancia un errore con messaggio che include lo status code
|
||||||
* 8. Se OK, svuota l'input
|
* 8. Se OK, svuota l'input e ricarica la lista chiamando fetchTodosUtente()
|
||||||
* 9. Ricarica la lista chiamando fetchTodosUtente()
|
* 10. Nel catch, mostra un messaggio di errore
|
||||||
|
* 11. Nascondi lo spinner di caricamento
|
||||||
*/
|
*/
|
||||||
async function addTodo() {
|
async function addTodo() {
|
||||||
}
|
}
|
||||||
@@ -119,8 +142,9 @@ async function addTodo() {
|
|||||||
* Passi:
|
* Passi:
|
||||||
* 1. Ricevi id e currentCompleted come parametri
|
* 1. Ricevi id e currentCompleted come parametri
|
||||||
* 2. Fai una PUT a /todos/{id} con body: {completato: !currentCompleted}
|
* 2. Fai una PUT a /todos/{id} con body: {completato: !currentCompleted}
|
||||||
* 3. Se non OK, mostra errore
|
* 3. Se non OK, lancia un errore con messaggio che include lo status code
|
||||||
* 4. Se OK, ricarica la lista chiamando fetchTodosUtente()
|
* 4. Se OK, ricarica la lista chiamando fetchTodosUtente()
|
||||||
|
* 5. Nel catch, mostra un messaggio di errore
|
||||||
*/
|
*/
|
||||||
async function toggleTodo(id, currentCompleted) {
|
async function toggleTodo(id, currentCompleted) {
|
||||||
}
|
}
|
||||||
@@ -130,11 +154,10 @@ async function toggleTodo(id, currentCompleted) {
|
|||||||
* FUNZIONE 4️⃣: Elimina TODO (DELETE)
|
* FUNZIONE 4️⃣: Elimina TODO (DELETE)
|
||||||
*
|
*
|
||||||
* Passi:
|
* Passi:
|
||||||
* 1. Chiedi conferma con confirm("Sicuro?")
|
* 1. Fai una DELETE a /todos/{id}
|
||||||
* 2. Se l'utente cancella, return
|
* 2. Se non OK, lancia un errore con messaggio che include lo status code
|
||||||
* 3. Fai una DELETE a /todos/{id}
|
* 3. Se OK, ricarica la lista chiamando fetchTodosUtente()
|
||||||
* 4. Se non OK, mostra errore
|
* 4. Nel catch, mostra un messaggio di errore
|
||||||
* 5. Se OK, ricarica la lista chiamando fetchTodosUtente()
|
|
||||||
*/
|
*/
|
||||||
async function deleteTodo(id) {
|
async function deleteTodo(id) {
|
||||||
}
|
}
|
||||||
@@ -164,33 +187,6 @@ async function deleteTodo(id) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FUNZIONE: Visualizza i TODO
|
|
||||||
* Funzione già fatta - non modificare
|
|
||||||
*/
|
|
||||||
function displayTodos(todos) {
|
|
||||||
|
|
||||||
if (!Array.isArray(todos) || todos.length === 0) {
|
|
||||||
todosContainer.innerHTML = '<div class="empty">Nessun TODO. Creane uno!</div>';
|
|
||||||
counter.classList.add('nascosto');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// CONTA COMPLETATI E NON
|
|
||||||
const completed = todos.filter(t => t.completato).length;
|
|
||||||
const pending = todos.length - completed;
|
|
||||||
|
|
||||||
// MOSTRA COUNTER
|
|
||||||
counter.innerHTML = `
|
|
||||||
📊 Totale: <strong>${todos.length}</strong> |
|
|
||||||
✅ Completati: <strong>${completed}</strong> |
|
|
||||||
⏳ In Sospeso: <strong>${pending}</strong>
|
|
||||||
`;
|
|
||||||
counter.classList.remove('nascosto');
|
|
||||||
|
|
||||||
creaCardsTodos(todos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== COLLEGA GLI EVENTI =====
|
// ===== COLLEGA GLI EVENTI =====
|
||||||
btnLoadTodos.addEventListener('click', fetchTodosUtente);
|
btnLoadTodos.addEventListener('click', fetchTodosUtente);
|
||||||
btnAddTodo.addEventListener('click', addTodo);
|
btnAddTodo.addEventListener('click', addTodo);
|
||||||
|
|||||||
@@ -15,88 +15,6 @@ const loading = document.getElementById('loading');
|
|||||||
const weatherContainer = document.getElementById('weatherContainer');
|
const weatherContainer = document.getElementById('weatherContainer');
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FUNZIONE: Gestione errori
|
|
||||||
*
|
|
||||||
* Mostra un messaggio di errore e logga in console
|
|
||||||
*/
|
|
||||||
function handleError(message) {
|
|
||||||
weatherContainer.innerHTML = `
|
|
||||||
<div class="error">
|
|
||||||
<strong>❌ ${message}</strong>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
console.error('Errore:', message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FUNZIONE: Ricerca il meteo per latitudine e longitudine
|
|
||||||
*
|
|
||||||
* Parametri obbligatori dell'API:
|
|
||||||
* - latitude: numero decimale
|
|
||||||
* - longitude: numero decimale
|
|
||||||
* - current: variabili da ottenere (separati da virgola)
|
|
||||||
* - timezone: 'auto' oppure fuso orario specifico
|
|
||||||
*
|
|
||||||
* Passi:
|
|
||||||
* 1. Leggi latitudine e longitudine dagli input
|
|
||||||
* 2. Valida che siano compilati
|
|
||||||
* 3. Mostra lo spinner di caricamento
|
|
||||||
* 4. Costruisci l'URL con i parametri corretti
|
|
||||||
* 5. Fai una GET a https://api.open-meteo.com/v1/forecast
|
|
||||||
* 6. Se non OK, mostra errore e return
|
|
||||||
* 7. Converti in JSON
|
|
||||||
* 8. Estrai data.current
|
|
||||||
* 9. Chiama displayWeather() per visualizzare
|
|
||||||
* 10. Nascondi lo spinner
|
|
||||||
*/
|
|
||||||
async function searchWeather() {
|
|
||||||
const lat = latitude.value;
|
|
||||||
const lon = longitude.value;
|
|
||||||
|
|
||||||
// VALIDAZIONE
|
|
||||||
if (!lat || !lon) {
|
|
||||||
handleError('Inserisci latitudine e longitudine');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loading.classList.remove('nascosto');
|
|
||||||
weatherContainer.innerHTML = '';
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 👇 SCRIVI QUI IL TUO CODICE 👇
|
|
||||||
|
|
||||||
// 1. Costruisci l'URL con i parametri corretti:
|
|
||||||
// const url = 'https://api.open-meteo.com/v1/forecast' +
|
|
||||||
// '?latitude=' + lat +
|
|
||||||
// '&longitude=' + lon +
|
|
||||||
// '¤t=temperature_2m,relative_humidity_2m,weather_code' +
|
|
||||||
// '&timezone=auto';
|
|
||||||
|
|
||||||
// 2. Fai la fetch
|
|
||||||
// const response = await fetch(url);
|
|
||||||
|
|
||||||
// 3. Se non OK, mostra errore e return
|
|
||||||
// if (!response.ok) {
|
|
||||||
// throw new Error('Errore nel caricamento dei dati meteo');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 4. Converti in JSON
|
|
||||||
// const data = await response.json();
|
|
||||||
|
|
||||||
// 5. Estrai i dati meteo e visualizza
|
|
||||||
// displayWeather(data.current, lat, lon);
|
|
||||||
|
|
||||||
throw new Error('Codice non implementato - Completa searchWeather()');
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
handleError(error.message);
|
|
||||||
} finally {
|
|
||||||
loading.classList.add('nascosto');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FUNZIONE: Visualizza i dati meteo
|
* FUNZIONE: Visualizza i dati meteo
|
||||||
* (Questa funzione è già fatta - non modificare)
|
* (Questa funzione è già fatta - non modificare)
|
||||||
@@ -122,7 +40,7 @@ function displayWeather(current, lat, lon) {
|
|||||||
|
|
||||||
const weather = weatherDescriptions[current.weather_code] || { emoji: '❓', descrizione: 'Sconosciuto' };
|
const weather = weatherDescriptions[current.weather_code] || { emoji: '❓', descrizione: 'Sconosciuto' };
|
||||||
|
|
||||||
const html = `
|
weatherContainer.innerHTML = `
|
||||||
<div class="weather-card">
|
<div class="weather-card">
|
||||||
<div class="location">
|
<div class="location">
|
||||||
📍 ${lat.toFixed(2)}°N, ${lon.toFixed(2)}°E
|
📍 ${lat.toFixed(2)}°N, ${lon.toFixed(2)}°E
|
||||||
@@ -140,10 +58,66 @@ function displayWeather(current, lat, lon) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
weatherContainer.innerHTML = html;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FUNZIONE: Gestione errori
|
||||||
|
* Mostra un messaggio di errore e logga in console
|
||||||
|
* Funzione già fatta - non modificare
|
||||||
|
*/
|
||||||
|
function mostraErrore(message) {
|
||||||
|
weatherContainer.innerHTML = `
|
||||||
|
<div class="error">
|
||||||
|
<strong>❌ ${message}</strong>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
console.error('Errore:', message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FUNZIONE: Ricerca il meteo per latitudine e longitudine
|
||||||
|
*
|
||||||
|
* Parametri obbligatori dell'API:
|
||||||
|
* - latitude: numero decimale
|
||||||
|
* - longitude: numero decimale
|
||||||
|
* - current: variabili da ottenere (separati da virgola)
|
||||||
|
* - timezone: 'auto' oppure fuso orario specifico
|
||||||
|
*/
|
||||||
|
async function searchWeather() {
|
||||||
|
const lat = latitude.value;
|
||||||
|
const lon = longitude.value;
|
||||||
|
|
||||||
|
// VALIDAZIONE
|
||||||
|
if (!lat || !lon) {
|
||||||
|
mostraErrore('Inserisci latitudine e longitudine');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.classList.remove('nascosto');
|
||||||
|
weatherContainer.innerHTML = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. Costruisci l'URL `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,relative_humidity_2m,weather_code&timezone=auto`
|
||||||
|
|
||||||
|
// 2. Fai la fetch
|
||||||
|
|
||||||
|
// 3. Se non OK, lancia un errore con lo status code
|
||||||
|
|
||||||
|
// 4. Converti in JSON
|
||||||
|
|
||||||
|
// 5. Estrai i dati meteo e visualizza con displayWeather()
|
||||||
|
|
||||||
|
throw new Error('Codice non implementato - Completa searchWeather()'); // Da Rimuovere
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
mostraErrore(error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.classList.add('nascosto');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ===== COLLEGA GLI EVENTI =====
|
// ===== COLLEGA GLI EVENTI =====
|
||||||
btnSearch.addEventListener('click', searchWeather);
|
btnSearch.addEventListener('click', searchWeather);
|
||||||
|
|
||||||
|
|||||||
@@ -14,80 +14,10 @@ const loading = document.getElementById('loading');
|
|||||||
const pokemonContainer = document.getElementById('pokemonContainer');
|
const pokemonContainer = document.getElementById('pokemonContainer');
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FUNZIONE: Gestione errori
|
|
||||||
*
|
|
||||||
* Mostra un messaggio di errore e logga in console
|
|
||||||
*/
|
|
||||||
function handleError(message) {
|
|
||||||
pokemonContainer.innerHTML = `
|
|
||||||
<div class="error">
|
|
||||||
<strong>❌ ${message}</strong>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
console.error('Errore:', message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FUNZIONE: Ricerca un Pokémon per nome o numero
|
|
||||||
*
|
|
||||||
* Parametri:
|
|
||||||
* - Accetta nome (in minuscolo) o numero ID
|
|
||||||
* - Ritorna oggetto con tutte le info del Pokémon
|
|
||||||
*
|
|
||||||
* Passi:
|
|
||||||
* 1. Leggi il valore dall'input
|
|
||||||
* 2. Converti a minuscolo e trim()
|
|
||||||
* 3. Valida che non sia vuoto
|
|
||||||
* 4. Mostra lo spinner di caricamento
|
|
||||||
* 5. Fai una GET a https://pokeapi.co/api/v2/pokemon/{input}
|
|
||||||
* 6. Se la risposta non è OK (404), mostra "Pokémon non trovato" e return
|
|
||||||
* 7. Converti in JSON
|
|
||||||
* 8. Chiama displayPokemon() per visualizzare
|
|
||||||
* 9. Nascondi lo spinner
|
|
||||||
*/
|
|
||||||
async function searchPokemon() {
|
|
||||||
const input = pokemonInput.value.trim().toLowerCase();
|
|
||||||
|
|
||||||
// VALIDAZIONE
|
|
||||||
if (!input) {
|
|
||||||
handleError('Inserisci il nome o numero di un Pokémon');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loading.classList.remove('nascosto');
|
|
||||||
pokemonContainer.innerHTML = '';
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 👇 SCRIVI QUI IL TUO CODICE 👇
|
|
||||||
|
|
||||||
// 1. Fai una fetch GET a: https://pokeapi.co/api/v2/pokemon/ + input
|
|
||||||
// const response = await fetch('https://pokeapi.co/api/v2/pokemon/' + input);
|
|
||||||
|
|
||||||
// 2. Controlla se la risposta è OK (non 404)
|
|
||||||
// if (!response.ok) {
|
|
||||||
// throw new Error('Pokémon non trovato');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 3. Converti in JSON
|
|
||||||
// const pokemon = await response.json();
|
|
||||||
|
|
||||||
// 4. Visualizza
|
|
||||||
// displayPokemon(pokemon);
|
|
||||||
|
|
||||||
throw new Error('Codice non implementato - Completa searchPokemon()');
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
handleError(error.message);
|
|
||||||
} finally {
|
|
||||||
loading.classList.add('nascosto');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FUNZIONE: Visualizza le informazioni del Pokémon
|
* FUNZIONE: Visualizza le informazioni del Pokémon
|
||||||
* (Questa funzione è già fatta - non modificare)
|
* Crea una card con nome, immagine, tipi, altezza e peso.
|
||||||
|
* Funzione già fatta - non modificare
|
||||||
*/
|
*/
|
||||||
function displayPokemon(pokemon) {
|
function displayPokemon(pokemon) {
|
||||||
|
|
||||||
@@ -99,7 +29,7 @@ function displayPokemon(pokemon) {
|
|||||||
const weight = (pokemon.weight / 10).toFixed(1); // Converti da hg a kg
|
const weight = (pokemon.weight / 10).toFixed(1); // Converti da hg a kg
|
||||||
const types = pokemon.types.map(t => t.type.name).join(', ');
|
const types = pokemon.types.map(t => t.type.name).join(', ');
|
||||||
|
|
||||||
const html = `
|
pokemonContainer.innerHTML = `
|
||||||
<div class="pokemon-card">
|
<div class="pokemon-card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2>#${id} - ${name}</h2>
|
<h2>#${id} - ${name}</h2>
|
||||||
@@ -129,10 +59,62 @@ function displayPokemon(pokemon) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
pokemonContainer.innerHTML = html;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FUNZIONE: Gestione errori
|
||||||
|
* Mostra un messaggio di errore e logga in console
|
||||||
|
* Funzione già fatta - non modificare
|
||||||
|
*/
|
||||||
|
function mostraErrore(message) {
|
||||||
|
console.error('Errore:', message);
|
||||||
|
pokemonContainer.innerHTML = `
|
||||||
|
<div class="error">
|
||||||
|
<strong>❌ ${message}</strong>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FUNZIONE: Ricerca un Pokémon per nome o numero
|
||||||
|
* La funzione cerca un Pokémon e lo visualizza. Se non trovato, mostra un errore.
|
||||||
|
*
|
||||||
|
* Parametri dell'API:
|
||||||
|
* - Accetta nome (in minuscolo) o numero ID
|
||||||
|
* - Ritorna oggetto con tutte le info del Pokémon
|
||||||
|
*/
|
||||||
|
async function searchPokemon() {
|
||||||
|
const input = pokemonInput.value.trim().toLowerCase();
|
||||||
|
|
||||||
|
// VALIDAZIONE
|
||||||
|
if (!input) {
|
||||||
|
mostraErrore('Inserisci il nome o numero di un Pokémon');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.classList.remove('nascosto');
|
||||||
|
pokemonContainer.innerHTML = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. Fai una fetch GET a: `https://pokeapi.co/api/v2/pokemon/${input}`
|
||||||
|
|
||||||
|
// 2. Controlla se la risposta è OK, altrimenti lancia un errore con "Pokémon non trovato"
|
||||||
|
|
||||||
|
// 3. Converti in JSON
|
||||||
|
|
||||||
|
// 4. Visualizza con displayPokemon()
|
||||||
|
|
||||||
|
throw new Error('Codice non implementato - Completa searchPokemon()'); // Da rimuovere
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
mostraErrore(error.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.classList.add('nascosto');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ===== COLLEGA GLI EVENTI =====
|
// ===== COLLEGA GLI EVENTI =====
|
||||||
btnSearch.addEventListener('click', searchPokemon);
|
btnSearch.addEventListener('click', searchPokemon);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user