// ESTÚDIO — Store persistente (localStorage) + reativo. Exporta window.STORE. // Fonte única de verdade para conteúdos, pautas e ideias. Semente = window.DATA. (function () { const D = window.DATA; const LS_KEY = "estudio_store_v1"; function clone(x) { return JSON.parse(JSON.stringify(x)); } function todayISO() { const n = new Date(); return n.getFullYear() + "-" + String(n.getMonth() + 1).padStart(2, "0") + "-" + String(n.getDate()).padStart(2, "0"); } // Hábitos & micro-tarefas padrão (rituais do dia da criadora) const DEFAULT_HABITOS = [ { id: "h1", emoji: "🙏", nome: "Café da manhã com presença", pontos: 5 }, { id: "h2", emoji: "📖", nome: "Leitura matinal", pontos: 10 }, { id: "h3", emoji: "✍️", nome: "Escrita matinal", pontos: 5 }, { id: "h4", emoji: "🏋️", nome: "Treino", pontos: 10 }, { id: "h5", emoji: "📵", nome: "Reduzir tempo em redes sociais", pontos: 5 }, { id: "h6", emoji: "💧", nome: "Beber 2L de água", pontos: 5 }, { id: "h7", emoji: "🎬", nome: "Gravar 1 conteúdo", pontos: 15 }, { id: "h8", emoji: "💡", nome: "Capturar 1 ideia no baú", pontos: 5 }, { id: "h9", emoji: "🗓️", nome: "Revisar a agenda do dia", pontos: 5 }, { id: "h10", emoji: "🧘", nome: "Pausa consciente / respirar", pontos: 5 }, ]; function seed() { return { conteudos: clone(D.conteudos || []), pautas: clone(D.pautas || []), habitos: clone(DEFAULT_HABITOS), habitLog: {}, habitSeq: 11, seq: 1, }; } function load() { try { const raw = localStorage.getItem(LS_KEY); if (raw) { const s = JSON.parse(raw); if (s && s.conteudos) { if (!s.habitos) s.habitos = clone(DEFAULT_HABITOS); if (!s.habitLog) s.habitLog = {}; if (!s.habitSeq) s.habitSeq = 11; return s; } } } catch (e) {} return seed(); } let state = load(); const subs = new Set(); const CLOUD_ID = "lorenna-estudio"; function persist() { try { localStorage.setItem(LS_KEY, JSON.stringify(state)); } catch (e) {} } function emit() { persist(); if (window.ESTUDIO_CLOUD) window.ESTUDIO_CLOUD.push(CLOUD_ID, state); subs.forEach((fn) => fn()); } // Ao abrir: puxa o estado da nuvem (se houver) e sobrepõe o local. if (window.ESTUDIO_CLOUD && window.ESTUDIO_CLOUD.enabled()) { window.ESTUDIO_CLOUD.pull(CLOUD_ID).then((remote) => { if (remote && remote.conteudos) { if (!remote.habitos) remote.habitos = clone(DEFAULT_HABITOS); if (!remote.habitLog) remote.habitLog = {}; if (!remote.habitSeq) remote.habitSeq = 11; state = remote; persist(); subs.forEach((fn) => fn()); } }); } function commit(next) { state = next; emit(); } function newId() { let n = (state.seq || 1); let id; do { id = "c" + (1000 + n); n++; } while (state.conteudos.some((c) => c.id === id)); state.seq = n; return id; } const DEFAULT_ROI = { autoridade: 0, venda: 0, compart: 0, seo: 0 }; const actions = { // ── Conteúdos ── addConteudo(partial) { const perfil = (partial && partial.perfis && partial.perfis[0]) || "lore"; const pil = (D.pilares.find((p) => p.perfil === perfil) || {}).id || "p1"; const base = { id: newId(), perfis: [perfil], titulo: "Novo conteúdo", pilar: pil, formato: "Reel", plats: ["instagram"], gravacao: "", publicacao: "", status: "Ideia", objetivo: "Atrair seguidores", energia: "media", tempo: "", resumo: "", roteiro: "", roi: { ...DEFAULT_ROI }, legendas: {}, checklist: [], }; const c = { ...base, ...(partial || {}) }; if (!c.roi) c.roi = { ...DEFAULT_ROI }; commit({ ...state, conteudos: [c, ...state.conteudos] }); return c.id; }, updateConteudo(id, patch) { commit({ ...state, conteudos: state.conteudos.map((c) => (c.id === id ? { ...c, ...patch } : c)) }); }, moveConteudo(id, status) { commit({ ...state, conteudos: state.conteudos.map((c) => (c.id === id ? { ...c, status } : c)) }); }, deleteConteudo(id) { commit({ ...state, conteudos: state.conteudos.filter((c) => c.id !== id) }); }, duplicateConteudo(id) { const c = state.conteudos.find((x) => x.id === id); if (!c) return null; const dup = { ...clone(c), id: newId(), titulo: c.titulo + " (cópia)", status: "Ideia", gravacao: "", publicacao: "" }; const idx = state.conteudos.findIndex((x) => x.id === id); const arr = state.conteudos.slice(); arr.splice(idx + 1, 0, dup); commit({ ...state, conteudos: arr }); return dup.id; }, toggleChecklist(id, idx) { commit({ ...state, conteudos: state.conteudos.map((c) => { if (c.id !== id) return c; const cl = (c.checklist || []).map((it, i) => (i === idx ? { ...it, ok: !it.ok } : it)); return { ...c, checklist: cl }; }) }); }, // Anexa a saída de um agente ao conteúdo (roteiro ou legenda) appendToConteudo(id, campo, texto, plat) { commit({ ...state, conteudos: state.conteudos.map((c) => { if (c.id !== id) return c; if (campo === "legenda" && plat) return { ...c, legendas: { ...(c.legendas || {}), [plat]: texto } }; const prev = c[campo] ? c[campo] + "\n\n" : ""; return { ...c, [campo]: prev + texto }; }) }); }, // ── Pautas ── addPauta(partial) { const perfil = (partial && partial.perfis && partial.perfis[0]) || "lore"; const pil = (D.pilares.find((p) => p.perfil === perfil) || {}).id || "p1"; let n = (state.seq || 1); let id; do { id = "pt" + (1000 + n); n++; } while (state.pautas.some((p) => p.id === id)); const base = { id, perfis: [perfil], titulo: "Nova ideia", pilar: pil, formato: "Reel", plats: ["instagram"], status: "ideia solta", origem: "Captura rápida" }; const p = { ...base, ...(partial || {}) }; commit({ ...state, seq: n, pautas: [p, ...state.pautas] }); return id; }, setPautaStatus(id, status) { commit({ ...state, pautas: state.pautas.map((p) => (p.id === id ? { ...p, status } : p)) }); }, // Transforma uma pauta/ideia em conteúdo de produção (sem recopiar à mão) pautaToConteudo(id) { const p = state.pautas.find((x) => x.id === id); if (!p) return null; const cid = actions.addConteudo({ perfis: p.perfis ? [...p.perfis] : ["lore"], titulo: p.titulo, pilar: p.pilar, formato: p.formato || "Reel", plats: p.plats ? [...p.plats] : ["instagram"], objetivo: p.objetivo || "Atrair seguidores", resumo: p.resumo || p.origem || "", status: "Roteirizado", origemPauta: id, }); // marca a pauta como aprovada/produção commit({ ...state, pautas: state.pautas.map((x) => (x.id === id ? { ...x, status: "em produção", virou: cid } : x)) }); return cid; }, resetAll() { commit(seed()); }, }; function subscribe(fn) { subs.add(fn); return () => subs.delete(fn); } function useStore() { const [, force] = React.useState(0); React.useEffect(() => subscribe(() => force((x) => x + 1)), []); return { state, actions }; } window.STORE = { get: () => state, actions, subscribe, useStore }; })();