474 lines
14 KiB
HTML
474 lines
14 KiB
HTML
<!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>
|