Skip to content

Commit 85fa710

Browse files
committed
feat: aggiungi gestione centralizzata del menu di navigazione con configurazione e icone
1 parent 0da8da4 commit 85fa710

4 files changed

Lines changed: 201 additions & 65 deletions

File tree

docs/NOTE_TECNICHE.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Questo documento contiene note tecniche utili per la gestione e manutenzione del
77
- [Sviluppo e Deploy](#sviluppo-e-deploy)
88
- [Configurazione Path](#configurazione-path)
99
- [Gestione Percorsi con Utility](#gestione-percorsi-con-utility)
10+
- [Gestione Menu di Navigazione](#gestione-menu-di-navigazione)
1011
- [Troubleshooting](#troubleshooting)
1112

1213
---
@@ -211,6 +212,142 @@ const siteUrl = `${site}${basePath}`;
211212

212213
---
213214

215+
## Gestione Menu di Navigazione
216+
217+
### Configurazione Centralizzata
218+
219+
Il menu di navigazione è ora gestito tramite un file di configurazione centralizzato che elimina la duplicazione del codice tra i diversi componenti menu.
220+
221+
**File di configurazione:** `src/config/navigation.ts`
222+
223+
```typescript
224+
export interface MenuItem {
225+
href: string;
226+
label: string;
227+
icon: string; // SVG path
228+
external?: boolean;
229+
}
230+
231+
export const menuItems: MenuItem[] = [
232+
{
233+
href: '/',
234+
label: 'Home',
235+
icon: 'M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6',
236+
},
237+
{
238+
href: '/numeri',
239+
label: 'Numeri',
240+
icon: 'M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z',
241+
},
242+
{
243+
href: '/tabella',
244+
label: 'Tabella',
245+
icon: 'M3 10h18M3 14h18m-9-4v8m-7 0V4a2 2 0 012-2h14a2 2 0 012 2v16a2 2 0 01-2 2H5a2 2 0 01-2-2z',
246+
},
247+
{
248+
href: '/info',
249+
label: 'Info',
250+
icon: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z',
251+
}
252+
];
253+
254+
// Funzione helper per ottenere l'URL completo di una voce di menu
255+
export function getMenuItemUrl(item: MenuItem, baseUrl: string): string {
256+
if (item.external || item.href.startsWith('http')) {
257+
return item.href;
258+
}
259+
260+
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
261+
return item.href === '/' ? (normalizedBaseUrl || '/') : `${normalizedBaseUrl}${item.href}`;
262+
}
263+
```
264+
265+
### Componenti Menu
266+
267+
Il progetto utilizza due componenti menu:
268+
269+
1. **HamburgerMenuNative.astro**: Menu nativo Astro (utilizzato nelle pagine principali)
270+
2. **HamburgerMenuReact.tsx**: Menu React (utilizzato nelle pagine con componenti React pesanti)
271+
272+
Entrambi ora utilizzano la configurazione centralizzata:
273+
274+
**Esempio utilizzo in HamburgerMenuNative.astro:**
275+
276+
```astro
277+
---
278+
import { menuItems, getMenuItemUrl } from '../config/navigation';
279+
const { baseUrl } = Astro.props;
280+
---
281+
282+
<nav class="menu-dropdown">
283+
<div class="menu-content">
284+
{menuItems.map((item) => (
285+
<a href={getMenuItemUrl(item, baseUrl)} class="menu-item">
286+
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
287+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d={item.icon} />
288+
</svg>
289+
{item.label}
290+
</a>
291+
))}
292+
</div>
293+
</nav>
294+
```
295+
296+
**Esempio utilizzo in HamburgerMenuReact.tsx:**
297+
298+
```tsx
299+
import { menuItems, getMenuItemUrl } from '../config/navigation';
300+
301+
export default function HamburgerMenuReact({ baseUrl }: HamburgerMenuReactProps) {
302+
return (
303+
<div className="py-2">
304+
{menuItems.map((item) => (
305+
<a
306+
key={item.href}
307+
href={getMenuItemUrl(item, baseUrl)}
308+
className="block px-4 py-2 text-gray-700 hover:bg-gray-100 transition-colors duration-150"
309+
onClick={closeMenu}
310+
>
311+
<div className="flex items-center">
312+
<svg className="w-5 h-5 mr-3 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
313+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={item.icon} />
314+
</svg>
315+
{item.label}
316+
</div>
317+
</a>
318+
))}
319+
</div>
320+
);
321+
}
322+
```
323+
324+
### Vantaggi della Centralizzazione
325+
326+
- **Single Source of Truth**: Tutte le voci di menu definite in un solo posto
327+
- **Coerenza**: Stesso ordine e struttura in tutti i menu
328+
- **Manutenibilità**: Aggiungere/rimuovere voci modificando solo il file di configurazione
329+
- **Type Safety**: TypeScript garantisce la struttura corretta delle voci di menu
330+
- **Gestione URL**: Funzione helper per gestire correttamente i percorsi in sviluppo e produzione
331+
332+
### Aggiungere una Nuova Voce di Menu
333+
334+
Per aggiungere una nuova voce al menu:
335+
336+
1. Aprire `src/config/navigation.ts`
337+
2. Aggiungere la nuova voce all'array `menuItems`:
338+
339+
```typescript
340+
{
341+
href: '/nuova-pagina',
342+
label: 'Nuova Pagina',
343+
icon: 'M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z',
344+
}
345+
```
346+
347+
3. I menu verranno automaticamente aggiornati in tutte le pagine
348+
349+
---
350+
214351
## Troubleshooting
215352

216353
### Favicon non viene caricato

src/components/HamburgerMenuNative.astro

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
// Nessun framework esterno, solo Astro nativo
33
import { normalizeBaseUrl } from '../lib/paths';
4+
import { menuItems, getMenuItemUrl } from '../config/navigation';
45
56
export interface Props {
67
baseUrl: string;
@@ -24,33 +25,14 @@ const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
2425
<!-- Menu Dropdown -->
2526
<nav class="menu-dropdown">
2627
<div class="menu-content">
27-
<a href={normalizedBaseUrl || '/'} class="menu-item">
28-
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
29-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
30-
</svg>
31-
Home
32-
</a>
33-
34-
<a href={`${normalizedBaseUrl}/numeri`} class="menu-item">
35-
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
36-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
37-
</svg>
38-
Numeri
39-
</a>
40-
41-
<a href={`${normalizedBaseUrl}/tabella`} class="menu-item">
42-
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
43-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 10h18M3 14h18m-9-4v8m-7 0V4a2 2 0 012-2h14a2 2 0 012 2v16a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
44-
</svg>
45-
Tabella
46-
</a>
47-
48-
<a href={`${normalizedBaseUrl}/info`} class="menu-item">
49-
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
50-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
51-
</svg>
52-
Info
53-
</a>
28+
{menuItems.map((item) => (
29+
<a href={getMenuItemUrl(item, baseUrl)} class="menu-item">
30+
<svg class="icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
31+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d={item.icon} />
32+
</svg>
33+
{item.label}
34+
</a>
35+
))}
5436
</div>
5537
</nav>
5638
</div>

src/components/HamburgerMenuReact.tsx

Lines changed: 16 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useState } from 'react';
22
import { normalizeBaseUrl } from '../lib/paths';
3+
import { menuItems, getMenuItemUrl } from '../config/navigation';
34

45
interface HamburgerMenuReactProps {
56
baseUrl: string;
@@ -62,44 +63,21 @@ export default function HamburgerMenuReact({ baseUrl }: HamburgerMenuReactProps)
6263
}`}
6364
>
6465
<div className="py-2">
65-
<a
66-
href={normalizedBaseUrl || '/'}
67-
className="block px-4 py-2 text-gray-700 hover:bg-gray-100 transition-colors duration-150"
68-
onClick={closeMenu}
69-
>
70-
<div className="flex items-center">
71-
<svg className="w-5 h-5 mr-3 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
72-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
73-
</svg>
74-
Home
75-
</div>
76-
</a>
77-
78-
<a
79-
href={`${normalizedBaseUrl}/tabella`}
80-
className="block px-4 py-2 text-gray-700 hover:bg-gray-100 transition-colors duration-150"
81-
onClick={closeMenu}
82-
>
83-
<div className="flex items-center">
84-
<svg className="w-5 h-5 mr-3 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
85-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 10h18M3 14h18m-9-4v8m-7 0V4a2 2 0 012-2h14a2 2 0 012 2v16a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
86-
</svg>
87-
Tabella
88-
</div>
89-
</a>
90-
91-
<a
92-
href={`${normalizedBaseUrl}/info`}
93-
className="block px-4 py-2 text-gray-700 hover:bg-gray-100 transition-colors duration-150"
94-
onClick={closeMenu}
95-
>
96-
<div className="flex items-center">
97-
<svg className="w-5 h-5 mr-3 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
98-
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
99-
</svg>
100-
Info
101-
</div>
102-
</a>
66+
{menuItems.map((item) => (
67+
<a
68+
key={item.href}
69+
href={getMenuItemUrl(item, baseUrl)}
70+
className="block px-4 py-2 text-gray-700 hover:bg-gray-100 transition-colors duration-150"
71+
onClick={closeMenu}
72+
>
73+
<div className="flex items-center">
74+
<svg className="w-5 h-5 mr-3 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
75+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d={item.icon} />
76+
</svg>
77+
{item.label}
78+
</div>
79+
</a>
80+
))}
10381
</div>
10482
</div>
10583
</div>

src/config/navigation.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
export interface MenuItem {
2+
href: string;
3+
label: string;
4+
icon: string; // SVG path o nome icona
5+
external?: boolean;
6+
}
7+
8+
export const menuItems: MenuItem[] = [
9+
{
10+
href: '/',
11+
label: 'Home',
12+
icon: 'M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6'
13+
},
14+
{
15+
href: '/numeri',
16+
label: 'Numeri',
17+
icon: 'M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z'
18+
},
19+
{
20+
href: '/tabella',
21+
label: 'Tabella',
22+
icon: 'M3 10h18M3 14h18m-9-4v8m-7 0V4a2 2 0 012-2h14a2 2 0 012 2v16a2 2 0 01-2 2H5a2 2 0 01-2-2z'
23+
},
24+
{
25+
href: '/info',
26+
label: 'Info',
27+
icon: 'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z'
28+
}
29+
];
30+
31+
// Funzione helper per ottenere l'URL completo di una voce di menu
32+
export function getMenuItemUrl(item: MenuItem, baseUrl: string): string {
33+
if (item.external || item.href.startsWith('http')) {
34+
return item.href;
35+
}
36+
37+
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
38+
return item.href === '/' ? (normalizedBaseUrl || '/') : `${normalizedBaseUrl}${item.href}`;
39+
}

0 commit comments

Comments
 (0)