diff --git a/backend/app/routers/content.py b/backend/app/routers/content.py
index dd6a5c3..8c9fc31 100644
--- a/backend/app/routers/content.py
+++ b/backend/app/routers/content.py
@@ -342,34 +342,14 @@ def approve_post(
return post
-@router.get("/suggestions")
-def get_topic_suggestions(
- character_id: int | None = Query(None),
- db: Session = Depends(get_db),
- current_user: User = Depends(get_current_user),
-):
- """Suggest 3 content topics based on character profile and recent posts."""
- if character_id:
- character = (
- db.query(Character)
- .filter(Character.id == character_id, Character.user_id == current_user.id)
- .first()
- )
- else:
- character = (
- db.query(Character)
- .filter(Character.user_id == current_user.id, Character.is_active == True)
- .first()
- )
- if not character:
- return {"suggestions": [], "character_id": None}
-
+def _generate_suggestions(db: Session, current_user: User, character) -> list[str]:
+ """Internal: call LLM to generate topic suggestions."""
provider_name = _get_setting(db, "llm_provider", current_user.id)
api_key = _get_setting(db, "llm_api_key", current_user.id)
model = _get_setting(db, "llm_model", current_user.id)
if not provider_name or not api_key:
- return {"suggestions": [], "character_id": character.id, "needs_setup": True}
+ return []
recent_posts = (
db.query(Post)
@@ -406,12 +386,174 @@ def get_topic_suggestions(
try:
result = llm.generate(prompt, system=system_prompt)
lines = [line.strip() for line in result.strip().splitlines() if line.strip()]
- suggestions = lines[:3]
+ return lines[:3]
except Exception:
- suggestions = []
+ return []
+
+
+@router.get("/suggestions")
+def get_topic_suggestions(
+ force: bool = Query(False),
+ db: Session = Depends(get_db),
+ current_user: User = Depends(get_current_user),
+):
+ """Get cached daily suggestions or generate new ones. Use force=true to regenerate."""
+ character = (
+ db.query(Character)
+ .filter(Character.user_id == current_user.id, Character.is_active == True)
+ .first()
+ )
+ if not character:
+ return {"suggestions": [], "character_id": None}
+
+ provider_name = _get_setting(db, "llm_provider", current_user.id)
+ api_key = _get_setting(db, "llm_api_key", current_user.id)
+ if not provider_name or not api_key:
+ return {"suggestions": [], "character_id": character.id, "needs_setup": True}
+
+ today = date.today().isoformat()
+
+ # Check cache
+ if not force:
+ cached = _get_setting(db, "daily_suggestions", current_user.id)
+ if cached and isinstance(cached, dict) and cached.get("date") == today:
+ return {
+ "suggestions": cached.get("suggestions", []),
+ "character_id": cached.get("character_id", character.id),
+ "character_name": cached.get("character_name", character.name),
+ "cached": True,
+ }
+
+ # Generate new suggestions
+ suggestions = _generate_suggestions(db, current_user, character)
+
+ # Save to cache
+ cache_data = {
+ "date": today,
+ "suggestions": suggestions,
+ "character_id": character.id,
+ "character_name": character.name,
+ }
+ existing = (
+ db.query(SystemSetting)
+ .filter(SystemSetting.key == "daily_suggestions", SystemSetting.user_id == current_user.id)
+ .first()
+ )
+ if existing:
+ existing.value = cache_data
+ existing.updated_at = datetime.utcnow()
+ else:
+ db.add(SystemSetting(key="daily_suggestions", value=cache_data, user_id=current_user.id))
+ db.commit()
return {
"suggestions": suggestions,
"character_id": character.id,
"character_name": character.name,
+ "cached": False,
}
+
+
+# === Saved Ideas (Swipe File) ===
+
+@router.get("/ideas")
+def get_saved_ideas(
+ db: Session = Depends(get_db),
+ current_user: User = Depends(get_current_user),
+):
+ """Get all saved ideas for the user."""
+ setting = (
+ db.query(SystemSetting)
+ .filter(SystemSetting.key == "saved_ideas", SystemSetting.user_id == current_user.id)
+ .first()
+ )
+ ideas = setting.value if setting and isinstance(setting.value, list) else []
+ return {"ideas": ideas, "total": len(ideas)}
+
+
+@router.post("/ideas")
+def save_idea(
+ data: dict,
+ db: Session = Depends(get_db),
+ current_user: User = Depends(get_current_user),
+):
+ """Save an idea for later use."""
+ text = data.get("text", "").strip()
+ if not text:
+ raise HTTPException(status_code=400, detail="Text is required")
+
+ setting = (
+ db.query(SystemSetting)
+ .filter(SystemSetting.key == "saved_ideas", SystemSetting.user_id == current_user.id)
+ .first()
+ )
+ ideas = setting.value if setting and isinstance(setting.value, list) else []
+
+ new_idea = {
+ "id": str(uuid.uuid4())[:8],
+ "text": text,
+ "note": data.get("note", ""),
+ "saved_at": datetime.utcnow().isoformat(),
+ "used": False,
+ }
+ ideas.insert(0, new_idea)
+
+ if setting:
+ setting.value = ideas
+ setting.updated_at = datetime.utcnow()
+ else:
+ db.add(SystemSetting(key="saved_ideas", value=ideas, user_id=current_user.id))
+ db.commit()
+ return new_idea
+
+
+@router.delete("/ideas/{idea_id}")
+def delete_idea(
+ idea_id: str,
+ db: Session = Depends(get_db),
+ current_user: User = Depends(get_current_user),
+):
+ """Delete a saved idea."""
+ setting = (
+ db.query(SystemSetting)
+ .filter(SystemSetting.key == "saved_ideas", SystemSetting.user_id == current_user.id)
+ .first()
+ )
+ if not setting or not isinstance(setting.value, list):
+ raise HTTPException(status_code=404, detail="Idea not found")
+
+ ideas = [i for i in setting.value if i.get("id") != idea_id]
+ if len(ideas) == len(setting.value):
+ raise HTTPException(status_code=404, detail="Idea not found")
+
+ setting.value = ideas
+ setting.updated_at = datetime.utcnow()
+ db.commit()
+ return {"ok": True}
+
+
+@router.post("/ideas/{idea_id}/mark-used")
+def mark_idea_used(
+ idea_id: str,
+ db: Session = Depends(get_db),
+ current_user: User = Depends(get_current_user),
+):
+ """Mark an idea as used."""
+ setting = (
+ db.query(SystemSetting)
+ .filter(SystemSetting.key == "saved_ideas", SystemSetting.user_id == current_user.id)
+ .first()
+ )
+ if not setting or not isinstance(setting.value, list):
+ raise HTTPException(status_code=404, detail="Idea not found")
+
+ for idea in setting.value:
+ if idea.get("id") == idea_id:
+ idea["used"] = True
+ break
+ else:
+ raise HTTPException(status_code=404, detail="Idea not found")
+
+ setting.updated_at = datetime.utcnow()
+ db.commit()
+ return {"ok": True}
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 45a3658..3d49735 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -18,6 +18,7 @@ import SocialAccounts from './components/SocialAccounts'
import CommentsQueue from './components/CommentsQueue'
import SettingsPage from './components/SettingsPage'
import EditorialCalendar from './components/EditorialCalendar'
+import SavedIdeas from './components/SavedIdeas'
import AdminSettings from './components/AdminSettings'
import LandingPage from './components/LandingPage'
import CookieBanner from './components/CookieBanner'
@@ -52,6 +53,7 @@ export default function App() {
+ {topic} +
++ Cattura spunti e topic interessanti. Usali quando vuoi per generare contenuti. +
+Nessuna idea salvata
++ Salva idee dalla Dashboard o aggiungile qui per usarle quando vuoi. +
++ {idea.text} +
+