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:
@@ -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"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user