Criando novo módulo Estúdio de Poesia e renomeando botões
This commit is contained in:
+191
@@ -5170,6 +5170,197 @@ const initApp = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// ESTÚDIO DE POESIA
|
||||
// ============================================================
|
||||
const poesiaModal = document.getElementById('poesiaModal');
|
||||
const btnClosePoesiaModal = document.getElementById('btnClosePoesiaModal');
|
||||
const barBtnPoesia = document.getElementById('barBtnPoesia');
|
||||
const btnOpenPoesiaHistory = document.getElementById('btnOpenPoesiaHistory');
|
||||
const poesiaHistoryModal = document.getElementById('poesiaHistoryModal');
|
||||
const btnClosePoesiaHistory = document.getElementById('btnClosePoesiaHistory');
|
||||
|
||||
const btnGeneratePoesia = document.getElementById('btnGeneratePoesia');
|
||||
const poesiaGenerateLoader = document.getElementById('poesiaGenerateLoader');
|
||||
const poesiaResultArea = document.getElementById('poesiaResultArea');
|
||||
const poesiaTextOutput = document.getElementById('poesiaTextOutput');
|
||||
const btnCopyPoesia = document.getElementById('btnCopyPoesia');
|
||||
const btnDownloadPoesiaPdf = document.getElementById('btnDownloadPoesiaPdf');
|
||||
|
||||
const poesiaTemaInput = document.getElementById('poesiaTemaInput');
|
||||
const poesiaFaixaEtaria = document.getElementById('poesiaFaixaEtaria');
|
||||
|
||||
let currentPoesia = null;
|
||||
let selectedEstrofes = 3;
|
||||
|
||||
// Seleção de estrofes
|
||||
document.querySelectorAll('.btn-poesia-estrofes').forEach(btn => {
|
||||
btn.addEventListener('click', (e) => {
|
||||
document.querySelectorAll('.btn-poesia-estrofes').forEach(b => b.classList.remove('active'));
|
||||
e.target.classList.add('active');
|
||||
selectedEstrofes = parseInt(e.target.dataset.estrofes);
|
||||
});
|
||||
});
|
||||
|
||||
// Abrir/Fechar Modal Principal
|
||||
if (barBtnPoesia) {
|
||||
barBtnPoesia.addEventListener('click', () => {
|
||||
poesiaModal.style.display = 'flex';
|
||||
poesiaTemaInput.value = '';
|
||||
poesiaResultArea.style.display = 'none';
|
||||
poesiaGenerateLoader.style.display = 'none';
|
||||
btnGeneratePoesia.disabled = false;
|
||||
currentPoesia = null;
|
||||
});
|
||||
}
|
||||
|
||||
if (btnClosePoesiaModal) {
|
||||
btnClosePoesiaModal.addEventListener('click', () => {
|
||||
poesiaModal.style.display = 'none';
|
||||
});
|
||||
}
|
||||
|
||||
// Abrir/Fechar Modal de Histórico
|
||||
if (btnOpenPoesiaHistory) {
|
||||
btnOpenPoesiaHistory.addEventListener('click', () => {
|
||||
poesiaHistoryModal.style.display = 'flex';
|
||||
loadPoesiaHistory();
|
||||
});
|
||||
}
|
||||
|
||||
if (btnClosePoesiaHistory) {
|
||||
btnClosePoesiaHistory.addEventListener('click', () => {
|
||||
poesiaHistoryModal.style.display = 'none';
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('click', (e) => {
|
||||
if (e.target === poesiaModal) poesiaModal.style.display = 'none';
|
||||
if (e.target === poesiaHistoryModal) poesiaHistoryModal.style.display = 'none';
|
||||
});
|
||||
|
||||
// Gerar Poesia
|
||||
if (btnGeneratePoesia) {
|
||||
btnGeneratePoesia.addEventListener('click', async () => {
|
||||
const tema = poesiaTemaInput.value.trim();
|
||||
const faixaEtaria = poesiaFaixaEtaria.value;
|
||||
|
||||
if (!tema) {
|
||||
showToast('Por favor, digite o tema da poesia.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
btnGeneratePoesia.disabled = true;
|
||||
poesiaGenerateLoader.style.display = 'flex';
|
||||
poesiaResultArea.style.display = 'none';
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/poesias/generate', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ faixaEtaria, estrofes: selectedEstrofes, tema })
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (response.ok && data.success) {
|
||||
currentPoesia = data.poesia;
|
||||
poesiaTextOutput.innerHTML = window.marked ? marked.parse(currentPoesia) : currentPoesia;
|
||||
poesiaResultArea.style.display = 'flex';
|
||||
showToast('Poesia criada com sucesso!', 'success');
|
||||
} else {
|
||||
showToast(data.error || 'Falha ao gerar poesia.', 'error');
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Erro na geração da poesia:', err);
|
||||
showToast('Erro de conexão ao gerar poesia.', 'error');
|
||||
} finally {
|
||||
btnGeneratePoesia.disabled = false;
|
||||
poesiaGenerateLoader.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Copiar e Baixar
|
||||
if (btnCopyPoesia) {
|
||||
btnCopyPoesia.addEventListener('click', () => {
|
||||
if (currentPoesia) {
|
||||
navigator.clipboard.writeText(currentPoesia);
|
||||
showToast('Poesia copiada para a área de transferência!', 'success');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (btnDownloadPoesiaPdf) {
|
||||
btnDownloadPoesiaPdf.addEventListener('click', () => {
|
||||
if (!currentPoesia) return;
|
||||
const element = document.createElement('div');
|
||||
element.innerHTML = window.marked ? marked.parse(currentPoesia) : currentPoesia;
|
||||
element.style.padding = '20px';
|
||||
element.style.fontFamily = 'Arial, sans-serif';
|
||||
element.style.color = '#333';
|
||||
|
||||
html2pdf().set({
|
||||
margin: 15,
|
||||
filename: 'poesia_pedagogica.pdf',
|
||||
image: { type: 'jpeg', quality: 0.98 },
|
||||
html2canvas: { scale: 2 },
|
||||
jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }
|
||||
}).from(element).save();
|
||||
});
|
||||
}
|
||||
|
||||
// Carregar Histórico
|
||||
async function loadPoesiaHistory() {
|
||||
const listContainer = document.getElementById('poesiaHistoryList');
|
||||
if (!listContainer) return;
|
||||
|
||||
listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Carregando...</p>';
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/poesias/list');
|
||||
const data = await response.json();
|
||||
|
||||
if (data && data.length > 0) {
|
||||
listContainer.innerHTML = '';
|
||||
data.forEach(item => {
|
||||
const date = new Date(item.created_at).toLocaleString('pt-BR');
|
||||
const div = document.createElement('div');
|
||||
div.className = 'history-item-card';
|
||||
div.style.cssText = 'background: rgba(255,255,255,0.02); padding: 14px; border-radius: 8px; border: 1px solid var(--border-light); display: flex; flex-direction: column; gap: 8px; cursor: pointer;';
|
||||
div.innerHTML = `
|
||||
<div style="display: flex; justify-content: space-between; align-items: flex-start;">
|
||||
<strong style="color: var(--brand-green); font-size: 0.95rem;">${item.faixa_etaria} (${item.estrofes} Estrofes)</strong>
|
||||
<span style="font-size: 0.75rem; color: var(--text-secondary);">${date}</span>
|
||||
</div>
|
||||
<p style="margin: 0; font-size: 0.85rem; color: var(--text-primary); opacity: 0.9;">Tema: ${item.tema}</p>
|
||||
`;
|
||||
|
||||
div.addEventListener('click', async () => {
|
||||
try {
|
||||
const res = await fetch(`/api/poesias/${item.id}`);
|
||||
const detail = await res.json();
|
||||
if (res.ok) {
|
||||
currentPoesia = detail.poesia;
|
||||
poesiaTextOutput.innerHTML = window.marked ? marked.parse(currentPoesia) : currentPoesia;
|
||||
poesiaResultArea.style.display = 'flex';
|
||||
poesiaHistoryModal.style.display = 'none';
|
||||
}
|
||||
} catch (err) {
|
||||
showToast('Erro ao carregar poesia.', 'error');
|
||||
}
|
||||
});
|
||||
|
||||
listContainer.appendChild(div);
|
||||
});
|
||||
} else {
|
||||
listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Nenhuma poesia salva ainda.</p>';
|
||||
}
|
||||
} catch (err) {
|
||||
listContainer.innerHTML = '<p style="text-align:center; color:#ef4444;">Erro ao carregar histórico.</p>';
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// BRINCARATIVO (CIRCUITOS PSICOMOTORES E BRINCADEIRAS)
|
||||
// ============================================================
|
||||
|
||||
+86
-4
@@ -239,7 +239,7 @@
|
||||
<span class="mode-icon">🎨</span> Atividade BNCC
|
||||
</button>
|
||||
<button type="button" class="btn-prompt-mode mode-music" data-mode="AUDIO" title="Compor e gerar uma música pedagógica">
|
||||
<span class="mode-icon">🎵</span> Criar Letra de Música
|
||||
<span class="mode-icon">🎵</span> Musicando Ideias
|
||||
</button>
|
||||
<button type="button" class="btn-prompt-mode mode-video" data-mode="VIDEO" title="Criar um roteiro ou animação de vídeo">
|
||||
<span class="mode-icon">🎬</span> Criar Vídeo
|
||||
@@ -247,11 +247,11 @@
|
||||
<button type="button" class="btn-prompt-mode mode-image" data-mode="IMAGE" title="Gerar ou desenhar uma ilustração educativa">
|
||||
<span class="mode-icon">🎨</span> Criar Imagem
|
||||
</button>
|
||||
<button type="button" class="btn-prompt-mode mode-poetry" data-mode="POETRY" title="Escrever uma poesia infantil pedagógica">
|
||||
<span class="mode-icon">📜</span> Criar Poesia
|
||||
<button type="button" class="btn-prompt-mode mode-poetry" id="barBtnPoesia" title="Escrever uma poesia infantil pedagógica">
|
||||
<span class="mode-icon">📜</span> Estúdio de Poesia
|
||||
</button>
|
||||
<button type="button" class="btn-prompt-mode mode-text" data-mode="TEXT" title="Escrever histórias, relatórios ou conversar">
|
||||
<span class="mode-icon">✍️</span> Criar História / Chat
|
||||
<span class="mode-icon">✍️</span> Inventando Historias
|
||||
</button>
|
||||
</div>
|
||||
<form id="chatForm">
|
||||
@@ -736,6 +736,88 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: Estúdio de Poesia -->
|
||||
<div id="poesiaModal" class="settings-modal" style="display: none;">
|
||||
<div class="settings-modal-content" style="max-width: 600px; width: 95%; max-height: 90vh; display: flex; flex-direction: column;">
|
||||
<div class="settings-modal-header" style="background: var(--bg-secondary); border-bottom: 1px solid var(--border-light);">
|
||||
<h3 style="display: flex; align-items: center; gap: 8px; font-family: 'Outfit', sans-serif;">📜 Estúdio de Poesia Camila AI</h3>
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<button id="btnOpenPoesiaHistory" class="btn-save-settings" style="background: transparent; border: 1px solid var(--border-light); color: var(--text-primary); padding: 6px 12px; font-size: 0.8rem;">
|
||||
🕒 Histórico
|
||||
</button>
|
||||
<button id="btnClosePoesiaModal" class="btn-close-modal" style="background: none; border: none; color: var(--text-secondary); cursor: pointer; font-size: 1.5rem;">×</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-modal-body" style="padding: 20px; overflow-y: auto; display: flex; flex-direction: column; gap: 18px; flex: 1;">
|
||||
|
||||
<div class="settings-group">
|
||||
<label style="color: var(--text-secondary); font-size: 0.82rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;">1. Faixa Etária (Idade da Criança)</label>
|
||||
<select id="poesiaFaixaEtaria" class="obs-select" style="width: 100%; margin-top: 4px;">
|
||||
<option value="Bebês (0 a 1 ano e 6 meses)">Bebês (0 a 1 ano e 6 meses)</option>
|
||||
<option value="Crianças bem pequenas (1 ano e 7 meses a 3 anos e 11 meses)">Crianças bem pequenas (1 ano e 7 meses a 3 anos e 11 meses)</option>
|
||||
<option value="Crianças pequenas (4 anos a 5 anos e 11 meses)" selected>Crianças pequenas (4 anos a 5 anos e 11 meses)</option>
|
||||
<option value="Ensino Fundamental I (6 a 10 anos)">Ensino Fundamental I (6 a 10 anos)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label style="color: var(--text-secondary); font-size: 0.82rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;">2. Quantidade de Estrofes</label>
|
||||
<div class="music-option-grid" style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 4px;">
|
||||
<button type="button" class="btn-poesia-estrofes" data-estrofes="2">2 Estrofes</button>
|
||||
<button type="button" class="btn-poesia-estrofes active" data-estrofes="3">3 Estrofes</button>
|
||||
<button type="button" class="btn-poesia-estrofes" data-estrofes="4">4 Estrofes</button>
|
||||
<button type="button" class="btn-poesia-estrofes" data-estrofes="5">5 Estrofes</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-group">
|
||||
<label style="color: var(--text-secondary); font-size: 0.82rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;">3. Tema da Poesia</label>
|
||||
<textarea id="poesiaTemaInput" placeholder="Ex: Higiene pessoal, amizade na escola, os animais da fazenda..." class="obs-input" style="width: 100%; min-height: 80px; padding: 10px; resize: vertical; margin-top: 4px; line-height: 1.4;"></textarea>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 10px; margin-top: 8px;">
|
||||
<button id="btnGeneratePoesia" style="background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: white; border: none; padding: 12px; border-radius: 8px; font-weight: 600; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px; transition: opacity 0.2s; box-shadow: 0 4px 12px rgba(16, 185, 129, 0.25);">
|
||||
<span>📜 Criar Poesia Personalizada</span>
|
||||
</button>
|
||||
<div id="poesiaGenerateLoader" style="display: none; align-items: center; justify-content: center; gap: 10px; color: var(--text-secondary); font-size: 0.9rem; padding: 10px; background: rgba(255, 255, 255, 0.02); border-radius: 8px;">
|
||||
<div class="record-spinner" style="width: 20px; height: 20px; border-width: 2px;"></div>
|
||||
<span>A IA está buscando inspiração e compondo sua poesia...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="poesiaResultArea" style="display: none; border-top: 1px solid var(--border-light); padding-top: 16px; flex-direction: column; gap: 14px;">
|
||||
<h4 style="margin: 0; color: var(--text-primary); font-size: 1rem; display: flex; align-items: center; gap: 6px;">✨ Sua Poesia Está Pronta!</h4>
|
||||
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<label style="color: var(--text-secondary); font-size: 0.78rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px;">Poesia Gerada</label>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<button id="btnCopyPoesia" style="background: none; border: 1px solid var(--border-light); color: var(--text-secondary); padding: 5px 10px; border-radius: 6px; font-size: 0.75rem; cursor: pointer; transition: all 0.2s;">📋 Copiar</button>
|
||||
<button id="btnDownloadPoesiaPdf" style="background: none; border: 1px solid var(--border-light); color: var(--text-secondary); padding: 5px 10px; border-radius: 6px; font-size: 0.75rem; cursor: pointer; transition: all 0.2s;">💾 Baixar PDF</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="poesiaTextOutput" class="markdown-body" style="background: var(--bg-secondary); padding: 16px; border-radius: 10px; font-size: 1rem; line-height: 1.6; border: 1px solid var(--border-light); color: var(--text-primary); margin: 0; min-height: 150px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: Histórico de Poesias -->
|
||||
<div id="poesiaHistoryModal" class="settings-modal" style="display: none; z-index: 1002;">
|
||||
<div class="settings-modal-content" style="max-width: 600px; width: 95%; max-height: 80vh; display: flex; flex-direction: column;">
|
||||
<div class="settings-modal-header" style="background: var(--bg-secondary); border-bottom: 1px solid var(--border-light);">
|
||||
<h3 style="display: flex; align-items: center; gap: 8px; font-family: 'Outfit', sans-serif;">🕒 Histórico de Poesias</h3>
|
||||
<button id="btnClosePoesiaHistory" class="btn-close-modal" style="background: none; border: none; color: var(--text-secondary); cursor: pointer; font-size: 1.5rem;">×</button>
|
||||
</div>
|
||||
<div class="settings-modal-body" style="padding: 20px; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; flex: 1;">
|
||||
<div id="poesiaHistoryList" style="display: flex; flex-direction: column; gap: 10px;">
|
||||
<p style="color: var(--text-secondary); font-size: 0.9rem; text-align: center; margin-top: 20px;">Carregando histórico...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal: Fábrica de Quadrinhos (Criação de histórias pedagógicas visuais) -->
|
||||
<div id="fabricaQuadrinhosModal" class="settings-modal" style="display: none;">
|
||||
<div class="settings-modal-content" style="max-width: 800px; width: 95%; max-height: 90vh; display: flex; flex-direction: column;">
|
||||
|
||||
@@ -1145,6 +1145,128 @@ app.delete('/api/brincar-ativo/:id', requireAuth, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// ============================================================
|
||||
// ROTAS DO ESTÚDIO DE POESIA
|
||||
// ============================================================
|
||||
app.post('/api/poesias/generate', requireAuth, async (req, res) => {
|
||||
const { faixaEtaria, estrofes, tema } = req.body;
|
||||
if (!faixaEtaria || !estrofes || !tema) {
|
||||
return res.status(400).json({ error: 'Faixa etária, quantidade de estrofes e tema são obrigatórios.' });
|
||||
}
|
||||
|
||||
try {
|
||||
let poesiaText = '';
|
||||
|
||||
const systemInstruction = `Você é um poeta pedagógico infantil especializado em criar poesias ritmadas, sonoras e adequadas para o desenvolvimento infantil no Brasil.
|
||||
REGRAS RÍGIDAS:
|
||||
- Escreva a poesia para a faixa etária: ${faixaEtaria}
|
||||
- A poesia DEVE ter EXATAMENTE ${estrofes} estrofes.
|
||||
- O tema da poesia é: "${tema}"
|
||||
- Use rimas claras e vocabulário apropriado para a idade.
|
||||
- Sua resposta deve conter APENAS a poesia formatada em Markdown, sem NENHUM comentário adicional, explicação, ou blocos de pensamento.
|
||||
- Responda EXCLUSIVAMENTE em Português do Brasil.`;
|
||||
|
||||
// Utilizando o Gemini diretamente
|
||||
if (process.env.GOOGLE_AI_API_KEY) {
|
||||
console.log('[Poesia] Usando API direta do Google Gemini...');
|
||||
const geminiUrl = `https://generativelanguage.googleapis.com/v1beta/models/${process.env.GOOGLE_AI_MODEL || 'gemini-2.5-flash'}:generateContent?key=${process.env.GOOGLE_AI_API_KEY}`;
|
||||
|
||||
const response = await fetch(geminiUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
contents: [{ parts: [{ text: systemInstruction }] }],
|
||||
generationConfig: { temperature: 0.7, maxOutputTokens: 2000 }
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errText = await response.text();
|
||||
throw new Error(`Erro na API oficial do Gemini: ${errText}`);
|
||||
}
|
||||
|
||||
const resData = await response.json();
|
||||
poesiaText = resData.candidates?.[0]?.content?.parts?.[0]?.text || '';
|
||||
|
||||
// Remover qualquer tag <think> residual (embora a instrução já previna)
|
||||
poesiaText = poesiaText.replace(/<think>[\s\S]*?(?:<\/think>|$)/g, '').trim();
|
||||
} else {
|
||||
throw new Error('Chave GOOGLE_AI_API_KEY não configurada no servidor.');
|
||||
}
|
||||
|
||||
if (!poesiaText) {
|
||||
throw new Error('Nenhuma poesia gerada.');
|
||||
}
|
||||
|
||||
const usuarioId = req.user?.id || '00000000-0000-0000-0000-000000000000';
|
||||
const dbRes = await dbPool.query(
|
||||
`INSERT INTO escola.poesias (usuario_id, faixa_etaria, estrofes, tema, poesia)
|
||||
VALUES ($1, $2, $3, $4, $5) RETURNING id, created_at`,
|
||||
[usuarioId, faixaEtaria, parseInt(estrofes), tema, poesiaText]
|
||||
);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
id: dbRes.rows[0].id,
|
||||
poesia: poesiaText,
|
||||
createdAt: dbRes.rows[0].created_at
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('Erro na geração de poesia:', err);
|
||||
res.status(500).json({ error: 'Erro ao gerar poesia: ' + err.message });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/poesias/list', requireAuth, async (req, res) => {
|
||||
const usuarioId = req.user?.id || '00000000-0000-0000-0000-000000000000';
|
||||
try {
|
||||
const dbRes = await dbPool.query(
|
||||
`SELECT id, faixa_etaria, estrofes, tema, created_at FROM escola.poesias WHERE usuario_id = $1 ORDER BY created_at DESC`,
|
||||
[usuarioId]
|
||||
);
|
||||
res.json(dbRes.rows);
|
||||
} catch (err) {
|
||||
console.error('Erro ao listar poesias:', err);
|
||||
res.status(500).json({ error: 'Erro ao listar histórico de poesias.' });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/poesias/:id', requireAuth, async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const usuarioId = req.user?.id || '00000000-0000-0000-0000-000000000000';
|
||||
try {
|
||||
const dbRes = await dbPool.query(
|
||||
`SELECT * FROM escola.poesias WHERE id = $1 AND usuario_id = $2`,
|
||||
[id, usuarioId]
|
||||
);
|
||||
if (dbRes.rows.length === 0) {
|
||||
return res.status(404).json({ error: 'Poesia não encontrada.' });
|
||||
}
|
||||
res.json(dbRes.rows[0]);
|
||||
} catch (err) {
|
||||
console.error('Erro ao buscar poesia:', err);
|
||||
res.status(500).json({ error: 'Erro ao buscar poesia.' });
|
||||
}
|
||||
});
|
||||
|
||||
app.delete('/api/poesias/:id', requireAuth, async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const usuarioId = req.user?.id || '00000000-0000-0000-0000-000000000000';
|
||||
try {
|
||||
const dbRes = await dbPool.query(
|
||||
`DELETE FROM escola.poesias WHERE id = $1 AND usuario_id = $2`,
|
||||
[id, usuarioId]
|
||||
);
|
||||
if (dbRes.rowCount === 0) {
|
||||
return res.status(404).json({ error: 'Poesia não encontrada ou não pertence ao usuário.' });
|
||||
}
|
||||
res.json({ success: true, message: 'Poesia deletada com sucesso.' });
|
||||
} catch (err) {
|
||||
console.error('Erro ao deletar poesia:', err);
|
||||
res.status(500).json({ error: 'Erro ao deletar poesia.' });
|
||||
}
|
||||
});
|
||||
|
||||
// Rota GET para obter configurações do agente
|
||||
app.get('/api/agent-config', requireAuth, (req, res) => {
|
||||
@@ -1345,6 +1467,17 @@ async function initDatabase() {
|
||||
atividade TEXT NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Poesias (Estúdio de Poesia)
|
||||
CREATE TABLE IF NOT EXISTS escola.poesias (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
usuario_id UUID NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
||||
faixa_etaria VARCHAR(100) NOT NULL,
|
||||
estrofes INTEGER NOT NULL,
|
||||
tema TEXT NOT NULL,
|
||||
poesia TEXT NOT NULL,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
`);
|
||||
|
||||
// Garantir que a coluna character_description_english exista na tabela projetos_comics
|
||||
|
||||
Reference in New Issue
Block a user