Tutti gli altri (6-10)

This commit is contained in:
2026-02-03 00:08:30 +01:00
parent 0043f1f83f
commit e6f6f17769
54 changed files with 3205 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Profilo Utente</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<a href="../index.html" style="position: absolute; top: 20px; left: 20px; text-decoration: none; color: #555; font-weight: bold; font-size: 14px;">← Dashboard</a>
<div class="card-container">
<div class="card-header">
<img id="img-profilo" src="https://placehold.co/150" alt="Foto Profilo">
<h2 id="nome-completo">Nome Cognome</h2>
<p id="ruolo" class="ruolo-badge">Ruolo</p>
</div>
<div class="card-body">
<div class="dettaglio">
<strong>Email:</strong>
<span id="email">...</span>
</div>
<div class="dettaglio">
<strong>Telefono:</strong>
<span id="telefono">...</span>
</div>
<div class="dettaglio">
<strong>Indirizzo:</strong>
<span id="indirizzo">...</span>
</div>
<div id="box-verifica" class="verifica nascosto">
✅ Utente Verificato
</div>
</div>
<div class="card-footer">
<button id="btn-stampa">Stampa Profilo</button>
</div>
</div>
<script src="script.js"></script>
</body>
</html>

View File

@@ -0,0 +1,53 @@
// DATI (Oggetto Singolo)
// Immagina che questi dati arrivino da un server o da un database.
const utente = {
nome: "Giulia",
cognome: "Verdi",
eta: 30,
email: "giulia.verdi@example.com",
telefono: "+39 333 1234567",
indirizzo: "Via Roma 10, Milano",
professione: "Graphic Designer",
fotoUrl: "https://randomuser.me/api/portraits/women/44.jpg", // Url di una foto vera
verificato: true // Prova a mettere false per vedere cosa succede
};
// 1. SELEZIONE ELEMENTI DOM
// Esercizio: Completa i querySelector abbinando gli ID corretti presi dall'HTML
const elNomeCompleto = document.querySelector(''); // es. #nome-completo
const elRuolo = document.querySelector('');
const elEmail = document.querySelector('');
const elTelefono = document.querySelector('');
const elIndirizzo = document.querySelector('');
const elImmagine = document.querySelector('');
const boxVerifica = document.querySelector('');
/**
* 2. RIEMPIMENTO DATI
* Ora devi prendere i dati dall'oggetto 'utente' e metterli dentro gli elementi HTML.
*/
// A. Testo Semplice (textContent)
// elNomeCompleto.textContent = ...
// ...
// B. Attributi (src)
// elImmagine.src = ...
// ...
// C. Logica Condizionale
// Se l'utente è "verificato" (true), mostriamo il box verde.
// Altrimenti lo lasciamo nascosto (o lo nascondiamo esplicitamente).
/**
* 3. EVENTI
* Fai funzionare il bottone "Stampa Profilo"
* Quando cliccato, deve lanciare un alert() con scritto: "Sto stampando il profilo di [NOME]"
* Alert permette di mostrare un messaggio all'utente e bloccare l'esecuzione finché non preme "OK".
* Il suo utilizzo è semplice: alert("Messaggio da mostrare");
*/
const btnStampa = document.querySelector('#btn-stampa');

View File

@@ -0,0 +1,105 @@
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /* Stesso font dashboard */
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); /* Stesso sfondo dashboard */
min-height: 100vh;
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
color: #2c3e50;
}
.card-container {
background: white;
width: 320px;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 15px 35px rgba(0,0,0,0.1);
text-align: center;
}
.card-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 30px 20px;
}
#img-profilo {
width: 100px;
height: 100px;
border-radius: 50%; /* Cerchio perfetto */
border: 4px solid white;
object-fit: cover;
margin-bottom: 10px;
}
h2 {
margin: 10px 0 5px 0;
font-size: 24px;
}
.ruolo-badge {
background: rgba(255, 255, 255, 0.2);
display: inline-block;
padding: 5px 15px;
border-radius: 20px;
font-size: 14px;
margin: 0;
}
.card-body {
padding: 20px;
text-align: left;
}
.dettaglio {
margin-bottom: 15px;
border-bottom: 1px solid #eee;
padding-bottom: 5px;
color: #555;
}
strong {
color: #333;
display: block;
font-size: 12px;
text-transform: uppercase;
letter-spacing: 1px;
}
.verifica {
text-align: center;
color: #27ae60;
font-weight: bold;
margin-top: 20px;
padding: 10px;
background-color: #e8f8f5;
border-radius: 5px;
}
.nascosto {
display: none;
}
.card-footer {
padding: 15px;
background: #f9f9f9;
}
button {
background: linear-gradient(to right, #667eea, #764ba2); /* Riprende l'header */
color: white;
border: none;
padding: 12px 25px;
border-radius: 30px; /* Bottone a pillola moderno */
cursor: pointer;
font-weight: bold;
box-shadow: 0 4px 15px rgba(118, 75, 162, 0.4);
transition: 0.2s;
}
button:hover {
transform: scale(1.05);
box-shadow: 0 6px 20px rgba(118, 75, 162, 0.6);
}

View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lista della Spesa</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<a href="../index.html" style="position: absolute; top: 20px; left: 20px; text-decoration: none; color: #555; font-weight: bold; font-size: 14px;">← Dashboard</a>
<div class="container">
<h1>🛒 Lista della Spesa</h1>
<div class="input-group">
</div>
<div class="totale-container">
</div>
<hr>
<ul id="lista-spesa">
</ul>
</div>
<script src="script.js"></script>
</body>
</html>

View File

@@ -0,0 +1,93 @@
// DATI INIZIALI
// Questa lista funge da "Database" locale. Tutto ciò che vedi a schermo DEVE derivare da qui.
// Inizialmente contiene due prodotti di esempio (rimuovete se volete)
let lista = [
{ prodotto: 'Pane', prezzo: 1.50, sbarrato: false },
{ prodotto: 'Latte', prezzo: 1.20, sbarrato: false },
{ prodotto: 'Uova', prezzo: 2.30, sbarrato: false },
{ prodotto: 'Mele', prezzo: 0.80, sbarrato: true },
{ prodotto: 'Caffè', prezzo: 3.50, sbarrato: false }
];
// Pre-esercizi: RIFERIMENTI AL DOM
// Seleziona gli elementi necessari che DEVI definire nell'HTML se mancano
const inputProdotto = document.querySelector('');
const inputPrezzo = document.querySelector('');
const btnAggiungi = document.querySelector('');
const listaSpesa = document.querySelector('');
const contenitoreTotale = document.querySelector('');
/**
* FUNZIONE 1: Visualizza/Aggiorna Lista
* Questa funzione è il "motore" grafico. Deve:
* 1. Pulire la lista attuale nel DOM
* 2. Ciclare l'array 'lista'
* 3. Per ogni elemento, chiamare la funzione 'creaElementoLista'
* 4. Chiamare la funzione 'aggiornaTotale' alla fine per ricalcolare il conto
*/
function aggiornaLista() {
}
/**
* FUNZIONE 2: Crea Elemento HTML (li)
* Questa funzione si occupa di creare il singolo pezzetto di HTML.
* Deve:
* 1. Creare un tag <li>
* 2. Impostare il testo (es. "Pane - 1.50 €")
* 3. Se l'elemento ha la proprietà .sbarrato === true, aggiungere la classe CSS 'preso'
* 4. Gestire il click: se clicco sull'li, devo chiamare la funzione toggleSbarrato(elemento)
* 5. Appendere l'li alla listaSpesa (ul)
*/
function creaElementoLista(elemento) {
}
/**
* FUNZIONE 3: Gestione Click (Toggle Sbarrato)
* Questa funzione viene chiamata quando clicco su una riga.
* Non modifica il DOM direttamente! Deve:
* 1. Cambiare la proprietà 'sbarrato' dell'oggetto (da true a false o viceversa)
* 2. Richiamare aggiornaLista() per ridisegnare tutto aggiornato
*/
function toggleSbarrato(elemento) {
}
/**
* FUNZIONE 4: Calcola Totale
* Deve:
* 1. Creare una variabile somma = 0
* 2. Ciclare l'array 'lista'
* 3. Sommare i prezzi
* 4. (Opzionale) Somma solo quelli NON sbarrati
* 5. Scrivere il risultato nel contenitoreTotale
*/
function aggiornaTotale() {
}
/**
* EVENTO PRINCIPALE: Click su Aggiungi
* 1. Leggere i valori degli input (value)
* Nota che il prezzo deve essere convertito in numero.
* Per farlo usa parseFloat(valore) o Number(valore)
* 2. Validazione: se i campi sono pieni e il prezzo > 0
* 3. Creare un nuovo oggetto { prodotto: ..., prezzo: ..., sbarrato: false }
* 4. Aggiungerlo all'array 'lista' (push)
* 5. Richiamare aggiornaLista()
* 6. Svuotare gli input
*/
btnAggiungi.addEventListener('click', function () {
});
// AVVIO
// Chiamata iniziale per mostrare i dati di esempio (Pane e Latte)
aggiornaLista();

View File

@@ -0,0 +1,112 @@
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /* Stesso font dashboard */
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); /* Stesso sfondo dashboard */
min-height: 100vh;
margin: 0;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
color: #2c3e50;
}
.container {
background: white;
width: 450px;
padding: 30px;
border-radius: 20px;
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.1);
}
.input-group {
display: flex;
gap: 10px;
margin-bottom: 20px;
flex-wrap: wrap;
}
input {
padding: 12px;
border: 2px solid #eee;
background-color: #f9f9f9;
border-radius: 10px;
flex: 1;
font-size: 1rem;
transition: 0.3s;
}
input:focus {
border-color: #007bff;
background-color: #fff;
outline: none;
}
/* Facciamo l'input del prezzo un po' più piccolo */
input[type="number"] {
flex: 0 0 80px;
}
button {
padding: 12px 25px;
background: linear-gradient(135deg, #28a745 0%, #218838 100%);
color: white;
border: none;
border-radius: 10px;
cursor: pointer;
font-weight: bold;
box-shadow: 0 4px 10px rgba(40, 167, 69, 0.3);
transition: transform 0.2s;
}
button:hover {
transform: translateY(-2px);
}
ul {
list-style: none;
padding: 0;
}
li {
background: #fff;
border: 1px solid #eee;
margin-bottom: 8px;
border-radius: 8px;
padding: 15px;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
transition: all 0.2s;
box-shadow: 0 2px 5px rgba(0,0,0,0.02);
}
li:hover {
background-color: #f8f9fa;
transform: translateX(5px);
border-color: #007bff;
}
h1 {
text-align: center;
color: #333;
}
.totale-container {
text-align: right;
font-size: 1.2em;
font-weight: bold;
color: #333;
margin-bottom: 10px;
}
/* Stili per la lista */
/* ESERCIZIO CSS:
Aggiungi qui sotto la classe .preso
Deve avere:
- testo sbarrato (text-decoration: line-through)
- colore grigino
- sfondo un po' scuro
*/

View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<title>Gestionale Dipendenti</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<a href="../index.html" style="position: absolute; top: 20px; left: 20px; text-decoration: none; color: #555; font-weight: bold; font-size: 14px;">← Dashboard</a>
<h1>Gestione Dipendenti</h1>
<div class="controls">
<div>
<h3>Aggiungi Nuovo</h3>
<input type="text" id="input-nome" placeholder="Nome">
<input type="text" id="input-ruolo" placeholder="Ruolo">
<button id="btn-aggiungi">Aggiungi</button>
</div>
<div>
<h3>Cerca</h3>
<input type="text" id="input-ricerca" placeholder="Cerca per nome...">
</div>
<div>
<!-- <h3>Azioni</h3> -->
<!-- Zona per extra bottoni futuri -->
</div>
</div>
<table>
<thead>
<tr>
<th>Nome</th>
<th>Ruolo</th>
<th>Azioni</th>
</tr>
</thead>
<tbody id="tabella-corpo">
</tbody>
</table>
<script src="script.js"></script>
</body>
</html>

View File

@@ -0,0 +1,137 @@
// DATI INIZIALI
const dipendenti = [
{ nome: "Mario Rossi", ruolo: "Sviluppatore" },
{ nome: "Luigi Bianchi", ruolo: "Sviluppatore" },
{ nome: "Paolo Gialli", ruolo: "Sviluppatore" },
{ nome: "Anna Neri", ruolo: "Sviluppatore" },
{ nome: "Carlo Verdi", ruolo: "Project Manager" },
{ nome: "Luca Bianchi", ruolo: "Designer" },
];
// RIFERIMENTI DOM
const tbody = document.querySelector('#tabella-corpo');
const btnAggiungi = document.querySelector('#btn-aggiungi');
const inputNome = document.querySelector('#input-nome');
const inputRuolo = document.querySelector('#input-ruolo');
const inputRicerca = document.querySelector('#input-ricerca');
/**
* FUNZIONE PRINCIPALE: Visualizza Tabella
* Questa funzione deve:
* - Pulire il contenuto del tbody
* - Per ogni dipendente nell'array passato come argomento:
* - Creare una riga (usando la funzione creaRiga)
* - Aggiungere la riga al tbody
*/
function visualizzaTabella(lista) {
}
/**
* FUNZIONE 1: Crea Riga
* Questa funzione deve:
* - Creare una riga (tr)
* - Creare 3 celle (td): Nome, Ruolo, Azioni
* - Popolare le celle Nome e Ruolo con i dati corretti
* - Nella cella Azioni, aggiungere un bottone "Elimina"
* - Aggiungere un event listener al bottone "Elimina" per rimuovere il dipendente dall'array e visualizzare la tabella
* - Aggiungere le tre celle alla riga
* - Aggiungere la riga al tbody
*
* Nota: Usare il metodo dipendenti.splice(i, 1) per rimuovere l'elemento dall'array
* e poi richiamare visualizzaTabella(dipendenti) per mostrare la tabella aggiornata.
*/
function creaRiga(dipendente, indice) {
}
/**
* FUNZIONE 2: Aggiungi Dipendente
* 1. Leggere i valori degli input
* 2. SE non sono vuoti:
* - Creare un oggetto { nome: ..., ruolo: ... }
* - Aggiungerlo all'array 'dipendenti'
* - Richiamare visualizzaTabella() per aggiornare la vista
* - Pulire gli input (settarli a stringa vuota)
*/
btnAggiungi.addEventListener('click', () => {
});
/**
* FUNZIONE 3: Ricerca
* 1. Leggere il testo nel campo ricerca
* 2. Filtrare l'array 'dipendenti' usando:
* - array.filter()
* - dipendente.nome.includes(testoRicerca)
* 3. Passare l'array filtrato a visualizzaTabella()
*/
inputRicerca.addEventListener('input', () => {
});
/**
* FUNZIONE 4: Emoji per Ruolo
* Aggiungere automaticamente un'emoji accanto al nome in base al ruolo.
*
* Passi:
* 1. Sviluppa la funzione getEmojiPerRuolo(ruolo) che ritorna:
* - "💻" per "Sviluppatore"
* - "🎨" per "Designer"
* - "👤" per altri ruoli
* 2. Modifica la funzione creaRiga per usare getEmojiPerRuolo
* 3. Usare la concatenazione stringhe per la cellaNome.textContent = emoji + " " + dipendente.nome;
*/
function getEmojiPerRuolo(ruolo) {
// Implementa la logica qui
}
// AVVIO
// Chiamare visualizzaTabella(dipendenti) all'inizio per mostrare i dati iniziali
visualizzaTabella(dipendenti);
/************************************************************************/
/************************* ESERCIZI EXTRA *******************************/
/************************************************************************/
/** ESERCIZIO EXTRA:
* Migliorare la funzione creaRiga per aggiungere una classe CSS speciale
* alle righe dei dipendenti che sono "Project Manager".
*
* Passi:
* 1. Aggiungi una classe .manager (o .evidenziato) che evidenzi la riga (es. background-color: #feffae;)
* 2. Modificare la funzione creaRiga:
* - Controllare se dipendente.ruolo === "Project Manager"
* - Se vero, aggiungere una classe CSS speciale alla riga (es. riga.classList.add('manager'))
*/
/** ESERCIZIO EXTRA 2:
* Aggiungere nel file index.html un bottone "Elimina Tutti" sopra la tabella.
*
* Passi:
* 1. Aggiungere il bottone con un id specifico (es. id="btn-elimina-tutti")
* 2. Stilizzare il bottone con CSS se necessario (colore rosso per esempio)
* 3. Aggiungere un event listener al bottone nel file script.js
* 4. Nell'event listener, svuotare l'array dipendenti (es. dipendenti.length = 0)
* 5. Richiamare visualizzaTabella(dipendenti) per aggiornare la vista
*/
/**
* ESERCIZIO EXTRA 3:
* Aggiungere un contatore sopra la tabella che mostra il numero totale di dipendenti.
*
* Passi:
* 1. Aggiungere un elemento HTML (es. un div o span) con un id specifico (es. id="contatore-dipendenti")
* 2. Mettere questo elemento sopra la tabella e stilizzarlo con CSS (metterlo almeno a destra)
* 3. Creare una funzione aggiornaContatore()
* - Questa funzione deve aggiornare il contenuto dell'elemento contatore con il numero di dipendenti (es. dipendenti.length)
* 4. Chiamare aggiornaContatore() ogni volta che la tabella viene aggiornata (dopo aggiungere, eliminare, o filtrare dipendenti)
*/

View File

@@ -0,0 +1,114 @@
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; /* Stesso font dashboard */
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); /* Stesso sfondo dashboard */
min-height: 100vh;
margin: 0;
padding: 20px;
justify-content: center;
align-items: center;
color: #2c3e50;
display: block;
padding: 40px;
}
.controls {
background: white;
padding: 25px;
border-radius: 15px;
border: none;
box-shadow: 0 10px 30px rgba(0,0,0,0.05);
margin-bottom: 30px;
}
/* Esempio di combinatore figlio diretto (>) */
.controls > div {
border-bottom: 1px solid #f0f0f0;
}
.controls > div:last-child {
border-bottom: none;
}
input[type="text"] {
padding: 10px;
border: 1px solid #ddd;
border-radius: 6px;
background: #f9f9f9;
}
button {
padding: 10px 20px;
background-color: #007bff; /* Blu base */
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
}
table {
width: 100%;
border-collapse: separate; /* Necessario per border-radius sulla tabella */
border-spacing: 0;
margin-top: 20px;
background: white;
border-radius: 15px;
overflow: hidden; /* Taglia gli angoli */
box-shadow: 0 10px 30px rgba(0,0,0,0.05);
}
th {
background: linear-gradient(135deg, #007bff 0%, #0056b3 100%);
color: white;
padding: 15px;
text-transform: uppercase;
font-size: 0.85rem;
letter-spacing: 1px;
border: none;
}
td {
border-bottom: 1px solid #eee;
padding: 15px;
color: #555;
}
tr:last-child td {
border-bottom: none;
}
/************************************************************/
/* ESERCIZI CSS: "RECUPERA GLI STILI PERSI" */
/* Usa solo selettori di TAG, ID (#), CLASSI (.) */
/* e combinatori di SPAZIO (discendente) */
/************************************************************/
/* LIVELLO 1: Il bottone Elimina (Discendenza)
Il bottone "Elimina" non ha classi, ma sappiamo che sta DENTRO il tbody.
Seleziona tutti i button che sono dentro il #tabella-corpo.
Obiettivo: Sfondo rosso (#ff4444), testo bianco, nessun bordo.
*/
/* LIVELLO 2: Interattività (Hover su discendente)
Vogliamo che il bottone elimina diventi più scuro quando ci passi sopra.
Obiettivo: Cambia il background-color in #cc0000 al passaggio del mouse.
Suggerimento: usa lo stesso selettore di prima + :hover
*/
/* LIVELLO 3: Leggibilità Riga (Hover su riga)
Vogliamo evidenziare tutta la riga (tr) della tabella quando il mouse ci passa sopra.
ATTENZIONE: Deve succedere solo nel corpo della tabella, non nell'intestazione!
Obiettivo: Background-color grigio chiaro (#f1f1f1) al passaggio del mouse sulla riga.
*/
/* LIVELLO 4 (Extra): Focus sugli Input
Vogliamo evidenziare gli input di testo quando l'utente ci clicca dentro (:focus).
Ma solo quelli dentro la zona .controls!
Obiettivo: Bordo blu (2px solid blue) e sfondo giallo chiaro (#ffffe0).
*/

View File

@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html lang="it">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hub Esercizi DOM</title>
<style>
/* RESET & BASE */
* { box-sizing: border-box; }
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); margin: 0; padding: 40px; min-height: 100vh; display: flex; align-items: center; justify-content: center; }
/* CONTENITORE PRINCIPALE */
.hub-container { background: white; width: 100%; max-width: 600px; padding: 40px; border-radius: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.1); }
h1 { text-align: center; color: #333; margin-bottom: 10px; font-size: 2.5rem; }
p.subtitle { text-align: center; color: #666; margin-bottom: 40px; font-size: 1.1rem; }
/* LISTA CARD */
.exercise-list { display: flex; flex-direction: column; gap: 20px; }
/* CARD ESERCIZIO */
.card { display: flex; align-items: center; text-decoration: none; background: #fff; border: 2px solid #eee; border-radius: 12px; padding: 20px; transition: all 0.3s ease; position: relative; overflow: hidden; }
.card:hover { transform: translateY(-5px); border-color: #007bff; box-shadow: 0 10px 20px rgba(0,123,255,0.15); }
/* ICONA E TESTI */
.icon { font-size: 2.5rem; margin-right: 20px; width: 50px; text-align: center; }
.info { flex: 1; }
.info h3 { margin: 0 0 5px 0; color: #2c3e50; font-size: 1.2rem; }
.info p { margin: 0; color: #7f8c8d; font-size: 0.9rem; }
/* TAG DIFFICOLTA' */
.badge { font-size: 0.75rem; font-weight: bold; padding: 4px 8px; border-radius: 6px; text-transform: uppercase; letter-spacing: 1px; margin-left: 10px; white-space: nowrap; }
.easy { background-color: #e8f5e9; color: #2e7d32; } /* Verde */
.medium { background-color: #fff3e0; color: #ef6c00; } /* Arancione */
.hard { background-color: #ffebee; color: #c62828; } /* Rosso */
/* FRECCIA AL PASSAGGIO DEL MOUSE */
.arrow { font-size: 1.5rem; color: #ccc; transition: 0.3s; }
.card:hover .arrow { color: #007bff; transform: translateX(5px); }
</style>
</head>
<body>
<div class="hub-container">
<h1>Esercizi DOM</h1>
<p class="subtitle">Corso Web Developer</p>
<div class="exercise-list">
<a href="01_card_profilo/index.html" class="card">
<div class="icon">👤</div>
<div class="info">
<h3>1. Profilo Utente <span class="badge easy">Base</span></h3>
<p>Manipolazione statica, Oggetti e attributi.</p>
</div>
<div class="arrow"></div>
</a>
<a href="02_lista_spesa/index.html" class="card">
<div class="icon">🛒</div>
<div class="info">
<h3>2. Lista Spesa <span class="badge medium">Intermedio</span></h3>
<p>Array, Cicli, Creazione elementi e Totali.</p>
</div>
<div class="arrow"></div>
</a>
<a href="03_gestionale/index.html" class="card">
<div class="icon">💼</div>
<div class="info">
<h3>3. Gestionale <span class="badge hard">Avanzato</span></h3>
<p>Tabelle, Filtri di ricerca, aggiunta/rimozione dipendenti.</p>
</div>
<div class="arrow"></div>
</a>
</div>
</div>
</body>
</html>