ripasso: fixes
This commit is contained in:
473
javascript/ripasso_completo/esercizio_3_api/index.html
Normal file
473
javascript/ripasso_completo/esercizio_3_api/index.html
Normal file
@@ -0,0 +1,473 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="it">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Esercizio 3 — La Biblioteca Online (API)</title>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Merriweather:wght@700&family=Inter:wght@400;500;600;700&display=swap');
|
||||
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
|
||||
body {
|
||||
font-family: 'Inter', 'Segoe UI', sans-serif;
|
||||
background: linear-gradient(145deg, #fdf8f0 0%, #f5f0e8 40%, #faf5ed 100%);
|
||||
color: #2d2418;
|
||||
padding: 24px;
|
||||
line-height: 1.6;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 880px;
|
||||
margin: 0 auto;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
backdrop-filter: blur(12px);
|
||||
border-radius: 20px;
|
||||
padding: 36px;
|
||||
box-shadow:
|
||||
0 1px 3px rgba(0,0,0,0.04),
|
||||
0 8px 32px rgba(139,90,43,0.08);
|
||||
border: 1px solid rgba(255,255,255,0.6);
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-family: 'Merriweather', Georgia, serif;
|
||||
font-size: 2.2em;
|
||||
margin-bottom: 6px;
|
||||
background: linear-gradient(135deg, #8b5a2b, #a0522d);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.sottotitolo {
|
||||
text-align: center;
|
||||
color: #94867a;
|
||||
font-size: 0.9em;
|
||||
font-weight: 500;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.avviso-server {
|
||||
text-align: center;
|
||||
background: linear-gradient(135deg, #fef3c7, #fef9c3);
|
||||
border: 1px solid #fbbf24;
|
||||
color: #92400e;
|
||||
padding: 12px 18px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.88em;
|
||||
font-weight: 500;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
|
||||
.avviso-server code {
|
||||
background: rgba(0,0,0,0.08);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* ─── STATISTICHE ─── */
|
||||
#stats {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 28px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.stat-box {
|
||||
background: linear-gradient(145deg, #fff, #faf5ed);
|
||||
border: 1px solid #e8ddd0;
|
||||
border-radius: 14px;
|
||||
padding: 18px 28px;
|
||||
text-align: center;
|
||||
min-width: 140px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.stat-box::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0; left: 0; right: 0;
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, #8b5a2b, #cd853f);
|
||||
opacity: 0;
|
||||
transition: opacity 0.25s;
|
||||
}
|
||||
|
||||
.stat-box:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 6px 20px rgba(139,90,43,0.1);
|
||||
}
|
||||
|
||||
.stat-box:hover::after { opacity: 1; }
|
||||
|
||||
.stat-box .label {
|
||||
font-size: 0.75em;
|
||||
color: #94867a;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.8px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.stat-box .valore {
|
||||
font-size: 2em;
|
||||
font-weight: 700;
|
||||
color: #8b5a2b;
|
||||
}
|
||||
|
||||
/* ─── LOADING ─── */
|
||||
#loading {
|
||||
display: none;
|
||||
text-align: center;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
#loading.visibile { display: block; }
|
||||
|
||||
.spinner {
|
||||
width: 40px; height: 40px;
|
||||
border: 4px solid #e8ddd0;
|
||||
border-top: 4px solid #8b5a2b;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.8s linear infinite;
|
||||
margin: 0 auto 12px;
|
||||
}
|
||||
|
||||
@keyframes spin { to { transform: rotate(360deg); } }
|
||||
|
||||
#loading p { color: #94867a; font-size: 0.9em; }
|
||||
|
||||
/* ─── SEZIONI ─── */
|
||||
.sezione {
|
||||
background: linear-gradient(145deg, #fdf8f0, #faf5ed);
|
||||
border: 1px solid #e8ddd0;
|
||||
border-radius: 14px;
|
||||
padding: 26px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.sezione h2 {
|
||||
font-size: 1.15em;
|
||||
margin-bottom: 18px;
|
||||
color: #8b5a2b;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* ─── FORM ─── */
|
||||
.form-riga {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.form-riga input,
|
||||
.form-riga select {
|
||||
flex: 1;
|
||||
min-width: 140px;
|
||||
padding: 11px 16px;
|
||||
border: 1.5px solid #e0d5c7;
|
||||
border-radius: 10px;
|
||||
font-size: 0.95em;
|
||||
font-family: inherit;
|
||||
background: rgba(255,255,255,0.85);
|
||||
color: #2d2418;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.form-riga input:focus,
|
||||
.form-riga select:focus {
|
||||
outline: none;
|
||||
border-color: #8b5a2b;
|
||||
box-shadow: 0 0 0 3px rgba(139,90,43,0.1);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.form-riga input::placeholder { color: #b8a898; }
|
||||
|
||||
/* ─── BOTTONI ─── */
|
||||
.bottoni {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 18px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 10px 22px;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
font-size: 0.9em;
|
||||
font-weight: 600;
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.btn-primario {
|
||||
background: linear-gradient(135deg, #8b5a2b, #a0522d);
|
||||
color: white;
|
||||
box-shadow: 0 2px 10px rgba(139,90,43,0.25);
|
||||
}
|
||||
|
||||
.btn-primario:hover {
|
||||
box-shadow: 0 4px 16px rgba(139,90,43,0.35);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-secondario {
|
||||
background: rgba(255,255,255,0.7);
|
||||
color: #5d4e37;
|
||||
border: 1.5px solid #e0d5c7;
|
||||
}
|
||||
|
||||
.btn-secondario:hover {
|
||||
background: #fff;
|
||||
border-color: #8b5a2b;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background: #fff5f5;
|
||||
color: #c53030;
|
||||
border: 1.5px solid #fcc;
|
||||
padding: 6px 14px;
|
||||
font-size: 0.85em;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.btn-danger:hover {
|
||||
background: #fed7d7;
|
||||
border-color: #c53030;
|
||||
}
|
||||
|
||||
/* ─── LISTA LIBRI ─── */
|
||||
#lista-libri {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
#lista-libri li {
|
||||
background: #fff;
|
||||
border: 1px solid #e8ddd0;
|
||||
border-left: 4px solid #8b5a2b;
|
||||
border-radius: 0 10px 10px 0;
|
||||
padding: 14px 18px;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
#lista-libri li:hover {
|
||||
background: #fdf8f0;
|
||||
box-shadow: 0 2px 8px rgba(139,90,43,0.08);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
#lista-libri li .info-libro { flex: 1; }
|
||||
|
||||
#lista-libri li .titolo-libro {
|
||||
font-weight: 700;
|
||||
color: #8b5a2b;
|
||||
font-size: 1.05em;
|
||||
}
|
||||
|
||||
#lista-libri li .dettagli-libro {
|
||||
color: #94867a;
|
||||
font-size: 0.85em;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.letto-badge {
|
||||
display: inline-block;
|
||||
padding: 2px 10px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.78em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.letto-si { background: #d1fae5; color: #065f46; }
|
||||
.letto-no { background: #fee2e2; color: #991b1b; }
|
||||
|
||||
/* ─── DETTAGLIO ─── */
|
||||
#dettaglio-libro {
|
||||
background: #fff;
|
||||
border: 1px solid #e8ddd0;
|
||||
border-radius: 12px;
|
||||
padding: 22px;
|
||||
margin-top: 16px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#dettaglio-libro.visibile {
|
||||
display: block;
|
||||
animation: slideIn 0.3s ease;
|
||||
}
|
||||
|
||||
#dettaglio-libro h3 {
|
||||
color: #8b5a2b;
|
||||
font-size: 1.2em;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
#dettaglio-libro .info {
|
||||
color: #5d4e37;
|
||||
font-size: 0.95em;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* ─── MESSAGGIO ─── */
|
||||
#messaggio {
|
||||
display: none;
|
||||
padding: 14px 18px;
|
||||
border-radius: 10px;
|
||||
margin: 16px 0;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
animation: slideIn 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes slideIn {
|
||||
from { opacity: 0; transform: translateY(-8px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.msg-successo {
|
||||
background: linear-gradient(135deg, #d1fae5, #a7f3d0);
|
||||
color: #065f46;
|
||||
border: 1px solid #6ee7b7;
|
||||
}
|
||||
|
||||
.msg-errore {
|
||||
background: linear-gradient(135deg, #fee2e2, #fecaca);
|
||||
color: #991b1b;
|
||||
border: 1px solid #fca5a5;
|
||||
}
|
||||
|
||||
/* ─── EMPTY STATE ─── */
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
padding: 40px 20px;
|
||||
color: #94867a;
|
||||
}
|
||||
|
||||
.empty-state .emoji { font-size: 3em; margin-bottom: 10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<h1>📚 La Biblioteca Online</h1>
|
||||
<p class="sottotitolo">Ripasso API — fetch, async/await, CRUD</p>
|
||||
|
||||
<div class="avviso-server">
|
||||
⚠️ Prima di iniziare, assicurati che il server sia avviato e funzionante.
|
||||
</div>
|
||||
|
||||
<!-- MESSAGGIO -->
|
||||
<div id="messaggio"></div>
|
||||
|
||||
<!-- STATISTICHE -->
|
||||
<div id="stats">
|
||||
<div class="stat-box">
|
||||
<div class="label">Totale Libri</div>
|
||||
<div class="valore" id="stat-totale">0</div>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<div class="label">Già Letti</div>
|
||||
<div class="valore" id="stat-letti">0</div>
|
||||
</div>
|
||||
<div class="stat-box">
|
||||
<div class="label">Da Leggere</div>
|
||||
<div class="valore" id="stat-da-leggere">0</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- LOADING -->
|
||||
<div id="loading">
|
||||
<div class="spinner"></div>
|
||||
<p>Caricamento in corso...</p>
|
||||
</div>
|
||||
|
||||
<!-- SEZIONE 1: CARICA LISTA -->
|
||||
<div class="sezione" id="sezione-lista">
|
||||
<h2>📋 Lista Libri</h2>
|
||||
<div class="bottoni">
|
||||
<button class="btn-primario" id="btn-carica-tutti">📥 Carica Tutti i Libri</button>
|
||||
</div>
|
||||
<ul id="lista-libri">
|
||||
<div class="empty-state">
|
||||
<div class="emoji">📚</div>
|
||||
<p>Clicca "Carica Tutti i Libri" per iniziare</p>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- SEZIONE 2: DETTAGLIO SINGOLO -->
|
||||
<div class="sezione" id="sezione-dettaglio">
|
||||
<h2>🔎 Cerca Libro per ID</h2>
|
||||
<div class="form-riga">
|
||||
<input type="number" id="input-id" placeholder="Inserisci ID libro (1-20)" min="1" max="20">
|
||||
<button class="btn-primario" id="btn-dettaglio">Cerca</button>
|
||||
</div>
|
||||
<div id="dettaglio-libro"></div>
|
||||
</div>
|
||||
|
||||
<!-- SEZIONE 3: AGGIUNGI LIBRO -->
|
||||
<div class="sezione" id="sezione-aggiungi">
|
||||
<h2>➕ Aggiungi Nuovo Libro</h2>
|
||||
<div class="form-riga">
|
||||
<input type="text" id="input-titolo" placeholder="Titolo">
|
||||
<input type="text" id="input-autore" placeholder="Autore">
|
||||
</div>
|
||||
<div class="form-riga">
|
||||
<select id="select-genere">
|
||||
<option value="">-- Genere --</option>
|
||||
<option value="Fantasy">🧙 Fantasy</option>
|
||||
<option value="Giallo">🔍 Giallo</option>
|
||||
<option value="Fantascienza">🚀 Fantascienza</option>
|
||||
<option value="Narrativa">📖 Narrativa</option>
|
||||
<option value="Horror">👻 Horror</option>
|
||||
<option value="Romanzo">💕 Romanzo</option>
|
||||
<option value="Umorismo">😂 Umorismo</option>
|
||||
</select>
|
||||
<input type="number" id="input-pagine" placeholder="Numero pagine" min="1">
|
||||
</div>
|
||||
<button class="btn-primario" id="btn-aggiungi">➕ Aggiungi Libro</button>
|
||||
</div>
|
||||
|
||||
<!-- SEZIONE 4: SEGNA COME LETTO -->
|
||||
<div class="sezione" id="sezione-modifica">
|
||||
<h2>✏️ Segna come Letto / Non Letto</h2>
|
||||
<div class="form-riga">
|
||||
<input type="number" id="input-modifica-id" placeholder="ID del libro" min="1">
|
||||
<select id="select-letto">
|
||||
<option value="true">✅ Letto</option>
|
||||
<option value="false">❌ Non letto</option>
|
||||
</select>
|
||||
<button class="btn-primario" id="btn-modifica">Aggiorna</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SEZIONE 5: ELIMINA -->
|
||||
<div class="sezione" id="sezione-elimina">
|
||||
<h2>🗑️ Elimina Libro</h2>
|
||||
<div class="form-riga">
|
||||
<input type="number" id="input-elimina-id" placeholder="ID del libro da eliminare" min="1">
|
||||
<button class="btn-danger" id="btn-elimina">🗑️ Elimina</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user