diff --git a/backend/routes/social.py b/backend/routes/social.py
index f0f4d30..494d9a2 100644
--- a/backend/routes/social.py
+++ b/backend/routes/social.py
@@ -1052,6 +1052,27 @@ async def get_suggestions(user=Depends(require_social_media)):
# ------------------------------------------------------------------
+# POST /api/social/ideas/save — Vorschlag als Idee speichern (zurückstellen)
+# ------------------------------------------------------------------
+@router.post("/ideas/save", status_code=201)
+async def save_idea(data: dict, user=Depends(require_social_media)):
+ """Speichert einen KI-Vorschlag als Idee in der DB (status='idea')."""
+ topic = (data.get("topic") or data.get("thema") or "").strip()
+ platform = data.get("platform", "both")
+ fmt = data.get("format", "post")
+ category = data.get("category")
+ if not topic:
+ raise HTTPException(400, "topic fehlt.")
+ with db() as conn:
+ cur = conn.execute(
+ """INSERT INTO social_content
+ (created_by, platform, format, topic, status, category, source)
+ VALUES (?,?,?,?,'idea',?,'saved_suggestion')""",
+ (user["id"], platform, fmt, topic, category),
+ )
+ return {"id": cur.lastrowid, "topic": topic, "status": "idea"}
+
+
# GET /api/social/content — alle Einträge
# ------------------------------------------------------------------
@router.get("/content")
diff --git a/backend/static/js/pages/social.js b/backend/static/js/pages/social.js
index bd1b5ba..3204630 100644
--- a/backend/static/js/pages/social.js
+++ b/backend/static/js/pages/social.js
@@ -422,13 +422,21 @@ window.Page_social = (() => {
padding:2px 6px;border-radius:4px">${_PL[idea.platform]||idea.platform}
-
+
+
+
+
`).join('');
@@ -453,6 +461,28 @@ window.Page_social = (() => {
}
});
});
+ box.querySelectorAll('.sm-save-idea').forEach(btn => {
+ btn.addEventListener('click', async e => {
+ e.stopPropagation();
+ btn.disabled = true;
+ btn.textContent = '…';
+ try {
+ await API.post('/social/ideas/save', {
+ topic: btn.dataset.thema,
+ format: btn.dataset.format,
+ platform: btn.dataset.platform,
+ category: btn.dataset.category || undefined,
+ });
+ btn.textContent = '✓ Gemerkt';
+ btn.style.background = 'var(--c-success)';
+ btn.style.color = '#fff';
+ btn.style.borderColor = 'var(--c-success)';
+ } catch {
+ btn.textContent = '📌 Merken';
+ btn.disabled = false;
+ }
+ });
+ });
box.querySelectorAll('.sm-idea').forEach(card => {
card.addEventListener('mouseenter', () => card.style.borderColor = 'var(--c-primary)');
card.addEventListener('mouseleave', () => card.style.borderColor = 'transparent');
@@ -1126,7 +1156,19 @@ window.Page_social = (() => {
${_esc(c.topic)}
${c.hook ? `🎣 ${_esc(c.hook)}
` : ''}
+ font-style:italic;margin-bottom:2px">🎣 ${_esc(c.hook)}` : ''}
+ ${c.post_url
+ ? `
+ 🔗 Post ansehen`
+ : c.status === 'published'
+ ? ``
+ : ''}
${c.status !== 'published' ? `
@@ -1173,14 +1215,65 @@ window.Page_social = (() => {
`).join('')}`;
el.querySelectorAll('[data-f]').forEach(b => b.addEventListener('click', () => load(b.dataset.f)));
- el.querySelectorAll('.sm-quick-post').forEach(b => b.addEventListener('click', async () => {
- const url = prompt('Post-URL (optional, leer lassen wenn keine):', '') ?? null;
- await API.patch(`/social/content/${b.dataset.id}`, {
- status: 'published',
- published_at: new Date().toISOString().slice(0,16),
- post_url: url || undefined,
+
+ // Quick-Post: Inline-Form statt prompt()
+ el.querySelectorAll('.sm-quick-post').forEach(b => b.addEventListener('click', () => {
+ const id = b.dataset.id;
+ UI.modal.open({
+ title: '📤 Als gepostet markieren',
+ body: `
+
+
+
+
+
+
+
+
`,
+ footer: `
+
+ `,
+ });
+ document.getElementById('qp-cancel')?.addEventListener('click', UI.modal.close);
+ document.getElementById(`qp-ok-${id}`)?.addEventListener('click', async () => {
+ const date = document.getElementById(`qp-date-${id}`)?.value
+ || new Date().toISOString().slice(0,10);
+ const url = document.getElementById(`qp-url-${id}`)?.value || undefined;
+ await API.patch(`/social/content/${id}`, {
+ status: 'published',
+ published_at: date,
+ post_url: url,
+ });
+ UI.modal.close();
+ load(filter);
+ });
+ }));
+
+ // "Link eintragen" für bereits veröffentlichte Posts ohne URL
+ el.querySelectorAll('.sm-add-url').forEach(b => b.addEventListener('click', () => {
+ const id = b.dataset.id;
+ UI.modal.open({
+ title: '🔗 Post-Link eintragen',
+ body: `
+
+
+
+
`,
+ footer: `
+
+ `,
+ });
+ document.getElementById('au-cancel')?.addEventListener('click', UI.modal.close);
+ document.getElementById(`au-ok-${id}`)?.addEventListener('click', async () => {
+ const url = document.getElementById(`au-url-${id}`)?.value;
+ if (!url) return;
+ await API.patch(`/social/content/${id}`, { post_url: url });
+ UI.modal.close();
+ load(filter);
});
- load(filter);
}));
el.querySelectorAll('.sm-exp').forEach(b => b.addEventListener('click', () => {
const d = el.querySelector(`#sm-d-${b.dataset.id}`);
diff --git a/backend/static/sw.js b/backend/static/sw.js
index 0f1edde..620e75f 100644
--- a/backend/static/sw.js
+++ b/backend/static/sw.js
@@ -3,7 +3,7 @@
Offline-Cache + Push Notifications + Tile-Cache
============================================================ */
-const CACHE_VERSION = 'by-v368';
+const CACHE_VERSION = 'by-v369';
const CACHE_STATIC = `${CACHE_VERSION}-static`;
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten