forked from phc/website
feat: implement localStorage functionality for MediaPesataApp and remove media.astro page
This commit is contained in:
@@ -120,12 +120,57 @@ const CORSI_DISPONIBILI: Corso[] = [
|
||||
]
|
||||
|
||||
function MediaPesataApp() {
|
||||
const [tipoStudente, setTipoStudente] = useState<TipoStudente>('triennale')
|
||||
const [corsiSelezionati, setCorsiSelezionati] = useState<CorsoSelezionato[]>([])
|
||||
// Funzioni per localStorage
|
||||
const loadFromStorage = () => {
|
||||
try {
|
||||
const savedData = localStorage.getItem('media-pesata-data')
|
||||
if (savedData) {
|
||||
const parsed = JSON.parse(savedData)
|
||||
return {
|
||||
tipoStudente: parsed.tipoStudente || 'triennale',
|
||||
corsiSelezionati: parsed.corsiSelezionati || [],
|
||||
sezioniAperte: parsed.sezioniAperte || {},
|
||||
mostraRisultati: parsed.mostraRisultati || false,
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Errore nel caricamento dei dati salvati:', error)
|
||||
}
|
||||
return {
|
||||
tipoStudente: 'triennale' as TipoStudente,
|
||||
corsiSelezionati: [],
|
||||
sezioniAperte: {},
|
||||
mostraRisultati: false,
|
||||
}
|
||||
}
|
||||
|
||||
const saveToStorage = (data: any) => {
|
||||
try {
|
||||
localStorage.setItem('media-pesata-data', JSON.stringify(data))
|
||||
} catch (error) {
|
||||
console.warn('Errore nel salvataggio dei dati:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// Inizializzazione con dati salvati
|
||||
const initialData = loadFromStorage()
|
||||
const [tipoStudente, setTipoStudente] = useState<TipoStudente>(initialData.tipoStudente)
|
||||
const [corsiSelezionati, setCorsiSelezionati] = useState<CorsoSelezionato[]>(initialData.corsiSelezionati)
|
||||
const [showCustomForm, setShowCustomForm] = useState(false)
|
||||
const [customCorso, setCustomCorso] = useState<CorsoCustom>({ nome: '', cfu: 0 })
|
||||
const [sezioniAperte, setSezioniAperte] = useState<Record<string, boolean>>({})
|
||||
const [mostraRisultati, setMostraRisultati] = useState(false)
|
||||
const [sezioniAperte, setSezioniAperte] = useState<Record<string, boolean>>(initialData.sezioniAperte)
|
||||
const [mostraRisultati, setMostraRisultati] = useState(initialData.mostraRisultati)
|
||||
|
||||
// Salva automaticamente quando cambiano i dati importanti
|
||||
useEffect(() => {
|
||||
const dataToSave = {
|
||||
tipoStudente,
|
||||
corsiSelezionati,
|
||||
sezioniAperte,
|
||||
mostraRisultati,
|
||||
}
|
||||
saveToStorage(dataToSave)
|
||||
}, [tipoStudente, corsiSelezionati, sezioniAperte, mostraRisultati])
|
||||
|
||||
const toggleSezione = (nomeSezione: string) => {
|
||||
setSezioniAperte(prev => ({
|
||||
@@ -237,6 +282,14 @@ function MediaPesataApp() {
|
||||
setCorsiSelezionati([])
|
||||
setCustomCorso({ nome: '', cfu: 0 })
|
||||
setShowCustomForm(false)
|
||||
setSezioniAperte({})
|
||||
setMostraRisultati(false)
|
||||
// Pulisce anche il localStorage
|
||||
try {
|
||||
localStorage.removeItem('media-pesata-data')
|
||||
} catch (error) {
|
||||
console.warn('Errore nella pulizia del localStorage:', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
import '@/styles/pages/media-pesata.css'
|
||||
import PageLayout from '../layouts/PageLayout.astro'
|
||||
---
|
||||
|
||||
<PageLayout title="Voto Laurea" description="Calcola la tua media pesata e il voto di laurea seguendo le regole del dipartimento">
|
||||
<div class="media-pesata-container">
|
||||
<h1>Voto Laurea</h1>
|
||||
<p>Calcola la tua media pesata e il voto con cui ti siederai alla discussione di laurea, seguendo le regole del dipartimento di Matematica.</p>
|
||||
|
||||
<div id="media-pesata-app"></div>
|
||||
</div>
|
||||
</PageLayout>
|
||||
|
||||
<script>
|
||||
// Importiamo e inizializziamo l'applicazione
|
||||
import('../client/MediaPesataApp')
|
||||
.then(module => {
|
||||
const { initMediaPesataApp } = module
|
||||
initMediaPesataApp()
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Errore nel caricamento dell\'applicazione:', error)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.media-pesata-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.media-pesata-container h1 {
|
||||
text-align: center;
|
||||
color: var(--palette-black);
|
||||
margin-bottom: 1rem;
|
||||
font-family: var(--font-display);
|
||||
font-weight: 700;
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.media-pesata-container p {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
margin-bottom: 2rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -47,29 +47,31 @@
|
||||
gap: 0.5rem;
|
||||
font-size: 1.1rem;
|
||||
cursor: pointer;
|
||||
padding: 0.75rem 1.5rem;
|
||||
border: 3px solid var(--palette-black);
|
||||
padding: 0.5rem 1rem;
|
||||
border: 2px solid var(--palette-black);
|
||||
border-radius: 6px;
|
||||
background: #fff;
|
||||
font-family: var(--font-secondary);
|
||||
font-weight: 600;
|
||||
transition: all 64ms linear;
|
||||
box-shadow: 4px 4px 0 0 var(--palette-black);
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.radio-group label:hover {
|
||||
transform: translate(-1px, -1px);
|
||||
box-shadow: 5px 5px 0 0 var(--palette-black);
|
||||
box-shadow: 3px 3px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.radio-group input[type='radio']:checked + span {
|
||||
background: var(--homepage-projects-bg);
|
||||
.radio-group label:active {
|
||||
transform: translate(1px, 1px);
|
||||
box-shadow: 1px 1px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.radio-group input[type='radio'] {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin: 0;
|
||||
accent-color: #007bff;
|
||||
}
|
||||
|
||||
/* Counter CFU */
|
||||
@@ -174,12 +176,18 @@
|
||||
transition: all 64ms linear;
|
||||
text-align: left;
|
||||
font-family: var(--font-secondary);
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.course-button:hover:not(:disabled) {
|
||||
background: var(--homepage-projects-bg);
|
||||
transform: translate(-1px, -1px);
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
box-shadow: 3px 3px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.course-button:active:not(:disabled) {
|
||||
transform: translate(1px, 1px);
|
||||
box-shadow: 1px 1px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.course-button:disabled {
|
||||
@@ -190,8 +198,8 @@
|
||||
|
||||
.course-button.selected {
|
||||
background: var(--guide-base);
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
transform: translate(1px, 1px);
|
||||
box-shadow: 1px 1px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.course-name {
|
||||
@@ -284,23 +292,35 @@
|
||||
.confirm-btn {
|
||||
background: #28a745;
|
||||
color: white;
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.confirm-btn:hover {
|
||||
background: #218838;
|
||||
transform: translate(-1px, -1px);
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
box-shadow: 3px 3px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.confirm-btn:active {
|
||||
transform: translate(1px, 1px);
|
||||
box-shadow: 1px 1px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
background: #6c757d;
|
||||
color: white;
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.cancel-btn:hover {
|
||||
background: #5a6268;
|
||||
transform: translate(-1px, -1px);
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
box-shadow: 3px 3px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.cancel-btn:active {
|
||||
transform: translate(1px, 1px);
|
||||
box-shadow: 1px 1px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
/* Sezione corsi selezionati */
|
||||
@@ -424,12 +444,18 @@
|
||||
justify-content: center;
|
||||
transition: all 64ms linear;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.remove-btn:hover {
|
||||
background: #b71c1c;
|
||||
transform: translate(-1px, -1px);
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
box-shadow: 3px 3px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.remove-btn:active {
|
||||
transform: translate(1px, 1px);
|
||||
box-shadow: 1px 1px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
/* Calcolo e risultati */
|
||||
@@ -671,12 +697,18 @@
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 64ms linear;
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.reset-btn:hover {
|
||||
background: #b71c1c;
|
||||
transform: translate(-1px, -1px);
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
box-shadow: 3px 3px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.reset-btn:active {
|
||||
transform: translate(1px, 1px);
|
||||
box-shadow: 1px 1px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.cfu-info {
|
||||
@@ -706,11 +738,17 @@
|
||||
transition: all 64ms linear;
|
||||
margin-bottom: 0.5rem;
|
||||
min-height: 36px;
|
||||
box-shadow: 1px 1px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.category-header:hover {
|
||||
background: #d9b3ff;
|
||||
transform: translate(-1px, -1px);
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.category-header:active {
|
||||
transform: translate(0px, 0px);
|
||||
box-shadow: 1px 1px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
@@ -751,12 +789,18 @@
|
||||
transition: all 64ms linear;
|
||||
font-family: var(--font-primary);
|
||||
display: inline-block;
|
||||
box-shadow: 4px 4px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.calculate-btn:hover {
|
||||
background: #2b8b47;
|
||||
transform: translate(-2px, -2px);
|
||||
box-shadow: 4px 4px 0 0 var(--palette-black);
|
||||
transform: translate(-1px, -1px);
|
||||
box-shadow: 5px 5px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
.calculate-btn:active {
|
||||
transform: translate(2px, 2px);
|
||||
box-shadow: 2px 2px 0 0 var(--palette-black);
|
||||
}
|
||||
|
||||
/* Info section */
|
||||
|
||||
Reference in New Issue
Block a user