14 Commits

Author SHA1 Message Date
Michele
5c06b1a342 fix: add trailing slashes to settings and prompts API calls
Without trailing slash, FastAPI's SPAStaticFiles catch-all intercepts
/api/settings and /api/prompts before the API router, returning HTML
instead of JSON (405 error in UI).

Affected endpoints:
- GET /api/settings → /api/settings/
- PUT /api/settings → /api/settings/
- GET /api/prompts → /api/prompts/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 12:54:46 +01:00
Michele
f154f1b2f6 feat(04-02): thumbnail PostCard e hint Unsplash in OutputReview
- PostCard: thumbnail 80x56px della cover image quando keyword e' URL
  - Rilevamento con startsWith('http')
  - object-cover, loading=lazy, onError nasconde se URL non valido
  - Posizionato dopo cover_title e prima dei metadati secondari
- OutputReview: hint discreto Unsplash sotto il box info edit inline
  - Visibile solo se unsplash_api_key_configured === false
  - Link a /impostazioni con stile amber discreto
  - Scompare automaticamente dopo configurazione Unsplash
  - Usa Link da react-router-dom (pattern codebase)
2026-03-09 08:16:55 +01:00
Michele
d537c03706 feat(04-02): Unsplash API key in types e pagina Settings
- Aggiunto unsplash_api_key a interface Settings
- Aggiunto unsplash_api_key_configured a interface SettingsStatus
- Aggiunta sezione 'Immagini' in Settings con campo API Key Unsplash
- Toggle visibilita' showUnsplashKey separato da showApiKey
- Helper text condizionale: messaggio diverso se key configurata o no
- Logica submit: unsplash_api_key vuota non sovrascrive quella esistente
- Reset campo dopo salvataggio come per api_key Claude
2026-03-09 08:15:42 +01:00
Michele
f449d945e9 feat(03-02): picker Swipe File nel form Genera Calendario + mark-used
- CalendarRequest in types.ts: aggiunto topic_overrides?: Record<number, string>
- hooks.ts: aggiunto useMarkSwipeUsed hook (POST /swipe/{id}/mark-used)
- GenerateCalendar.tsx: sezione Topic Override con griglia 13 slot
  - Bottone "Da Swipe File" per aprire picker inline per ogni slot
  - Picker mostra lista idee con nicchia badge e badge Usato
  - Selezione assegna topic allo slot e chiama mark-used
  - Bottone X per rimuovere override da uno slot
  - Override inclusi in CalendarRequest.topic_overrides al submit
  - Riepilogo counter override selezionati
2026-03-09 00:33:00 +01:00
Michele
d379789ec0 feat(03-01): pagina SwipeFile UI + TanStack hooks + navigazione
- frontend/src/types.ts: aggiunge SwipeItem, SwipeItemCreate, SwipeItemUpdate, SwipeListResponse
- frontend/src/api/hooks.ts: aggiunge useSwipeItems, useAddSwipeItem, useUpdateSwipeItem, useDeleteSwipeItem
- frontend/src/pages/SwipeFile.tsx: pagina completa con form aggiunta, filtro nicchia, modifica inline, eliminazione con dialog conferma, data relativa
- frontend/src/components/Sidebar.tsx: aggiunge voce "Swipe File" con icona Lightbulb
- frontend/src/App.tsx: registra route /swipe-file
- TypeScript + build Vite: nessun errore
2026-03-09 00:25:04 +01:00
Michele
ad2483d48d feat(02-02): OutputReview summary counter with regenerated/edited tracking
- Add regeneratedSlots Set to track regenerated post indices
- Add summary counter showing: N post, X generati, Y rigenerati, Z modificati
- Counter updates in real-time after each regeneration or inline edit
- Pass isRegenerated prop to PostCard for visual badge
- Update info box to mention regen feature with RefreshCw icon
- Use JSON.stringify comparison for manual edit detection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 21:03:11 +01:00
Michele
3488023142 feat(02-02): PostCard regen button with inline form, topic override, and regenerated badge
- Add handleRegen function with topic/notes override support
- Add inline popover form with optional topic and notes fields
- Add isRegenerated prop with amber RefreshCw badge for regenerated posts
- Regen button positioned in card header next to expand/collapse chevron
- Form appears below header with Rigenera/Annulla actions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 21:01:47 +01:00
Michele
ca3dd59072 feat(02-01): prompt editor UI with types, hooks, page, route, sidebar
- Add PromptInfo, PromptListResponse, PromptDetail types
- Add usePromptList, usePrompt, useSavePrompt, useResetPrompt hooks
- Create PromptEditor page with two-column layout, live variables
- Add /prompt-editor route in App.tsx
- Add Prompt Editor nav item with Pencil icon in Sidebar
- TypeScript compiles without errors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 20:57:01 +01:00
Michele
d8e3eb9415 fix(01): calendar slot merge in OutputReview for PN/Schwartz badges
GenerateResponse now includes calendar field from backend.
OutputReview merges CalendarSlot into PostResult via slot_index,
enabling BadgePN, BadgeSchwartz rendering and Retry button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 03:14:07 +01:00
Michele
a5d1c15c3a feat(01-04): pagine GenerateCalendar, OutputReview, GenerateSingle complete
- GenerateCalendar.tsx: form con obiettivo+settimane+brand+tono+nicchie
  - Pulsante Genera disabilitato senza API key con banner link a Impostazioni
  - Async submit: mutation ritorna job_id, mostra ProgressIndicator
  - Auto-navigate a /risultati/:jobId quando job completato
- OutputReview.tsx: carica job results via useJobResults(jobId)
  - Griglia PostCard responsive con conteggio success/failed
  - Stato locale per edit inline (aggiornato da PostCard.onEdit)
  - Download CSV via useDownloadEditedCsv (POST con edits) con due pulsanti (header + footer)
- GenerateSingle.tsx: form con tipo PN, livello Schwartz, nicchia, formato narrativo
  - Topic opzionale (altrimenti generato dall'AI)
  - Anteprima risultato con PostCard+SlideViewer e download CSV singolo
2026-03-08 02:29:17 +01:00
Michele
9e5bddc312 feat(01-04): SlideViewer con edit inline e ProgressIndicator con polling
- SlideViewer.tsx: navigazione frecce sinistra/destra tra 8 slide (Cover + 6 centrali + CTA)
  - EditableField component: click-to-edit per ogni campo (input/textarea)
  - Dot indicators + keyboard navigation (frecce sinistra/destra)
  - Caption Instagram editabile con contatore caratteri
  - Callback onEdit propaga modifiche al parent
- ProgressIndicator.tsx: polling real-time via useJobStatus(jobId)
  - Barra progresso visuale con percentuale
  - Lista post con icone stato: pending/running/success/failed
  - onComplete(jobId) chiamato quando status diventa 'completed'
  - Poll ogni 2s (condizionale nel hook, si ferma quando completed/failed)
2026-03-08 02:26:54 +01:00
Michele
a2ebd72041 feat(01-04): badge PN/Schwartz e PostCard con stati success/failed/pending
- BadgePN.tsx: 6 colori distinti per tipi PN (valore/storytelling/news/riprova_sociale/coinvolgimento/promozione)
- BadgeSchwartz.tsx: 5 livelli L1-L5 con tooltip descriptivo, colori progressivi
- PostCard.tsx: stati success (espandibile con SlideViewer) / failed (errore + pulsante Riprova) / pending (loader)
- SlideViewer.tsx: stub per compilazione (completato nel task successivo)
- PostCard usa useGenerateSingle() per rigenerazione inline post falliti
2026-03-08 02:25:17 +01:00
Michele
738a877d39 feat(01-04): layout, routing, API hooks, tipi TypeScript, Dashboard, Settings
- types.ts: CalendarSlot, GeneratedPost, PostResult, JobStatus, Settings, SettingsStatus
- api/client.ts: aggiunto apiGet, apiPost, apiPut, apiDownload, triggerDownload
- api/hooks.ts: 10+ hooks TanStack Query (settings, generate, job polling, CSV export)
- components/Layout.tsx + Sidebar.tsx: sidebar stone/amber palette con 4 nav link
- pages/Dashboard.tsx: banner API key, quick actions link, step guide
- pages/Settings.tsx: form completo (API key password, LLM select, brand, nicchie checkbox)
- App.tsx: 5 route con BrowserRouter basename='/postgenerator', QueryClientProvider, Layout
2026-03-08 02:23:55 +01:00
Michele
62f4b487b0 feat(01-01): React + Vite + Tailwind v4 SPA scaffold con API client
- Vite react-ts project con base: '/postgenerator/' (Pitfall #9 risolto)
- Tailwind v4 via @tailwindcss/vite plugin + @import "tailwindcss" in index.css
- react-router-dom con BrowserRouter basename="/postgenerator"
- @tanstack/react-query con QueryClientProvider
- lucide-react installato per icone
- src/api/client.ts: API_BASE='/postgenerator/api', apiFetch<T> con error handling
- Dev proxy: /postgenerator/api -> http://localhost:8000 (strip /postgenerator)
- App.tsx: HomePage placeholder "Setup completo", struttura Routes pronta
- Build Vite: 253.90kB JS + 5.53kB CSS, nessun errore TypeScript
2026-03-08 01:55:19 +01:00