registri dei piani in git (AI-OS#309)

Refs gitea:Adriano/AI-OS#310

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-10-06 10:36:26 +02:00
parent 9126af28ce
commit b913a2bf90
94 changed files with 40294 additions and 0 deletions
+95
View File
@@ -0,0 +1,95 @@
### Task 9: Toggle "Mostra tag" — endpoint cookie e cablaggio
**Files:**
- Create: `src/pages/api/admin/showtags.ts`
- Modify: `src/components/Header.astro` (script del pulsante)
**Interfaces:**
- Consumes: `locals.user` dal middleware (rotta sotto `/api/admin`, quindi login garantito).
- Produces: `POST /api/admin/showtags` con body `{ on: boolean }`; imposta/rimuove il cookie `showtags`; `403` se il ruolo non è `superuser`/`admin`.
- [ ] **Step 1: Crea l'endpoint**
Crea `src/pages/api/admin/showtags.ts`:
```typescript
import type { APIRoute } from 'astro';
export const prerender = false;
const json = (status: number, body: object) =>
new Response(JSON.stringify(body), { status, headers: { 'Content-Type': 'application/json' } });
export const POST: APIRoute = async ({ request, cookies, locals }) => {
const role = locals.user!.role;
if (role !== 'superuser' && role !== 'admin') return json(403, { error: 'Permessi insufficienti' });
let data: { on?: unknown };
try { data = await request.json(); } catch { return json(400, { error: 'Dati non validi.' }); }
if (data.on) {
cookies.set('showtags', '1', { httpOnly: true, sameSite: 'lax', path: '/', secure: import.meta.env.PROD });
} else {
cookies.delete('showtags', { path: '/' });
}
return json(200, { on: Boolean(data.on) });
};
```
- [ ] **Step 2: Cabla il pulsante nell'header**
In `src/components/Header.astro`, dentro il blocco `<script>` esistente (dopo il codice del burger), aggiungi:
```javascript
const tagsBtn = document.getElementById('toggle-tags');
if (tagsBtn) {
// Lo stato attuale è riflesso server-side; il testo lo deriviamo dal cookie.
const on = document.cookie.split('; ').some((c) => c === 'showtags=1');
tagsBtn.textContent = on ? 'Nascondi tag' : 'Mostra tag';
tagsBtn.addEventListener('click', async () => {
const res = await fetch('/api/admin/showtags', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ on: !on }),
});
if (res.ok) location.reload();
else alert('Operazione non riuscita.');
});
}
```
Nota: il cookie `showtags` è `httpOnly`, quindi `document.cookie` non lo espone. Per riflettere lo stato senza reload, l'header riceve già `showTags` come prop: passa lo stato al pulsante via attributo. Correzione da applicare in questo step — nel markup del Task 8 il pulsante diventa:
```astro
<button type="button" class="umenu__tags" id="toggle-tags" data-on={Astro.props.showTags ? '1' : '0'}>{Astro.props.showTags ? 'Nascondi tag' : 'Mostra tag'}</button>
```
e lo script usa `data-on`:
```javascript
const tagsBtn = document.getElementById('toggle-tags');
if (tagsBtn) {
const on = tagsBtn.dataset.on === '1';
tagsBtn.addEventListener('click', async () => {
const res = await fetch('/api/admin/showtags', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ on: !on }),
});
if (res.ok) location.reload();
else alert('Operazione non riuscita.');
});
}
```
- [ ] **Step 3: Verifica build**
Run: `npm run build`
Expected: build OK.
- [ ] **Step 4: Commit**
```bash
git add src/pages/api/admin/showtags.ts src/components/Header.astro
git commit -m "feat(showtags): endpoint cookie + toggle nel menu utente"
```
---