Consolidação do swipe file

This commit is contained in:
Lucas Santana 2024-12-18 18:12:28 -03:00
parent 323c9aa2b1
commit 37b736ae53
4 changed files with 193 additions and 33 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -6,7 +6,7 @@ let user_id = null;
let expires = null;
// URL base da API do Bubble no Launchr
const API_URL = 'https://launchr.com.br/version-test/api/1.1/wf';
const API_URL = 'https://launchr.com.br/api/1.1/wf';
// Recuperar o token e informações armazenadas ao iniciar a extensão
chrome.storage.local.get(['authToken', 'negocios_id', 'negocios_nome', 'user_id', 'expires'], (result) => {
@ -21,12 +21,13 @@ chrome.storage.local.get(['authToken', 'negocios_id', 'negocios_nome', 'user_id'
// Função para lidar com erros de autenticação
function handleAuthError() {
// Remover o token e informações armazenadas
authToken = null;
chrome.storage.local.remove(['authToken', 'negocios_id', 'negocios_nome', 'user_id', 'expires'], () => {
console.log('Token de autenticação removido.');
// Opcional: Notificar o usuário sobre a necessidade de login
});
chrome.storage.local.remove(
['authToken', 'negocios_id', 'negocios_nome', 'user_id', 'expires'],
() => {
console.log('Token removido devido a erro de autenticação');
}
);
}
// Listener para mensagens
@ -194,24 +195,64 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
return true;
} else if (request.action === 'saveSwipeFile') {
// Verificar se temos um token válido
if (!authToken) {
sendResponse({
success: false,
error: 'Usuário não autenticado. Por favor, faça login novamente.'
});
return true;
}
fetch(`${API_URL}/novo_swipe_file`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': authToken
'Authorization': authToken // Garantir que o token está no formato correto
},
body: JSON.stringify(request.data)
body: JSON.stringify({
negocio_id: request.data.negocio_id,
conteudo: request.data.conteudo,
nome_autor: request.data.nome_autor,
link_autor: request.data.link_autor,
link_post: request.data.link_post
})
})
.then(response => {
if (!response.ok) throw new Error('Erro na requisição');
if (response.status === 401) {
// Token expirado ou inválido
handleAuthError(); // Função que limpa o token e força novo login
throw new Error('Sessão expirada. Por favor, faça login novamente.');
}
if (!response.ok) {
throw new Error('Erro na requisição: ' + response.status);
}
return response.json();
})
.then(data => {
sendResponse({ success: true, data });
if (data.response && data.response.swipe_file_id) {
chrome.storage.local.set({
lastSwipeFileId: data.response.swipe_file_id
});
sendResponse({
success: true,
swipeFileId: data.response.swipe_file_id
});
} else {
throw new Error('Resposta inválida da API');
}
})
.catch(error => {
console.error('Erro ao salvar swipe file:', error);
sendResponse({ success: false, error: error.message });
sendResponse({
success: false,
error: error.message || 'Erro ao salvar o swipe file'
});
// Se for erro de autenticação, redirecionar para login
if (error.message.includes('401') || error.message.includes('expirada')) {
chrome.runtime.sendMessage({ action: 'showLogin' });
}
});
return true;

View File

@ -5,6 +5,47 @@
<title>Launchr</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<style>
.modal-content {
border-radius: 1rem;
border: none;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}
.modal-body {
padding: 2rem;
}
.btn {
padding: 0.75rem 1.5rem;
font-weight: 500;
border-radius: 0.5rem;
}
.btn-secondary {
background-color: #f3f4f6;
border: none;
color: #374151;
}
.btn-secondary:hover {
background-color: #e5e7eb;
color: #1f2937;
}
.btn-primary {
background-color: #4F46E5;
border: none;
}
.btn-primary:hover {
background-color: #4338CA;
}
.text-success {
color: #10B981 !important;
}
</style>
</head>
<body class="bg-light" style="width: 400px; min-height: 500px;">
<!-- Área de Login -->
@ -12,14 +53,14 @@
<!-- Logo -->
<div class="d-flex align-items-center mb-4">
<img src="./images/logo.png" alt="Launchr" height="32" class="me-2">
<small class="text-muted">Version 1.3.6</small>
<small class="text-muted">Versão 1.3.6</small>
</div>
<h1 class="display-6 text-primary mb-4">Let's get started</h1>
<h1 class="display-6 text-primary mb-4">Vamos começar</h1>
<form id="loginForm">
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<label for="email" class="form-label">E-mail</label>
<div class="input-group">
<span class="input-group-text">
<i class="bi bi-envelope"></i>
@ -29,7 +70,7 @@
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<label for="password" class="form-label">Senha</label>
<div class="input-group">
<span class="input-group-text">
<i class="bi bi-lock"></i>
@ -39,14 +80,14 @@
<i class="bi bi-eye"></i>
</button>
</div>
<a href="#" class="text-decoration-none small d-block mt-2">Forgot password?</a>
<a href="#" class="text-decoration-none small d-block mt-2">Esqueceu sua senha?</a>
</div>
<button type="submit" class="btn btn-primary w-100 py-2 mt-3">LOGIN</button>
<button type="submit" class="btn btn-primary w-100 py-2 mt-3">ENTRAR</button>
<div class="text-center mt-4">
<span class="text-muted">New here? </span>
<a href="#" class="text-decoration-none">Create your account</a>
<span class="text-muted">Novo por aqui? </span>
<a href="#" class="text-decoration-none">Criar uma conta</a>
</div>
</form>
</div>
@ -71,7 +112,7 @@
</button>
</div>
<!-- Avatar do usuário com dropdown -->
<!-- Avatar do usuário com menu -->
<div class="navbar-nav">
<div class="nav-item dropdown">
<div class="rounded-circle bg-primary d-flex align-items-center justify-content-center"
@ -82,12 +123,10 @@
<span class="text-white fw-medium">IL</span>
</div>
<ul class="dropdown-menu dropdown-menu-end py-2" style="min-width: 200px;" aria-labelledby="userDropdown">
<!-- Seleção de Negócio -->
<!-- Nome do Negócio -->
<li class="px-3 mb-2">
<small class="text-muted d-block mb-1">Selecione o Negócio</small>
<select id="negociosSelect" class="form-select form-select-sm">
<!-- Opções serão preenchidas via JavaScript -->
</select>
<small class="text-muted d-block mb-1">Negócio</small>
<span id="negocioNome" class="d-block text-truncate"></span>
</li>
<li><hr class="dropdown-divider"></li>
<li><button class="dropdown-item text-danger" id="logoutButton">Sair</button></li>
@ -104,7 +143,13 @@
<form id="postForm" class="bg-white p-4 rounded shadow-sm">
<div class="mb-3">
<label for="author" class="form-label">Autor</label>
<input type="text" class="form-control" id="author" readonly>
<input type="text" class="form-control" id="author">
</div>
<div class="mb-3">
<label for="postLink" class="form-label">Link do Post</label>
<input type="url" class="form-control" id="postLink"
placeholder="https://www.linkedin.com/posts_...">
</div>
<div class="mb-3">
@ -113,7 +158,7 @@
</div>
<button type="button" id="saveSwipeFileButton" class="btn btn-primary w-100">
Enviar Post
Salvar Post
</button>
</form>
</div>
@ -139,6 +184,24 @@
</div>
</div>
<!-- Modal de Sucesso -->
<div class="modal fade" id="successModal" tabindex="-1" aria-labelledby="successModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body text-center p-4">
<div class="mb-4">
<i class="bi bi-check-circle-fill text-success" style="font-size: 3rem;"></i>
</div>
<h5 class="modal-title mb-3" id="successModalLabel">Seu Swipe File foi criado com sucesso</h5>
<div class="d-grid gap-2">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fechar janela</button>
<a href="#" id="viewPostLink" class="btn btn-primary" target="_blank">Visualizar Post</a>
</div>
</div>
</div>
</div>
</div>
<script src="lib/bootstrap.bundle.min.js"></script>
<script src="popup.js"></script>
</body>

View File

@ -161,6 +161,7 @@ document.addEventListener('DOMContentLoaded', () => {
(response) => {
if (response.success) {
showLoggedInSection();
updateNegocioDisplay(); // Atualizar nome do negócio
loadPostData();
} else {
alert(response.error || 'Erro ao fazer login');
@ -172,9 +173,10 @@ document.addEventListener('DOMContentLoaded', () => {
// Gerenciar envio do post
document.getElementById('saveSwipeFileButton')?.addEventListener('click', async () => {
const content = document.getElementById('content').value;
const author = document.getElementById('author').value;
// Buscar ID do negócio do storage
chrome.storage.local.get(['negocios_id'], async (result) => {
// Buscar dados do negócio do storage
chrome.storage.local.get(['negocios_id', 'negocios_nome'], async (result) => {
if (!result.negocios_id) {
alert('Erro ao identificar o negócio.');
return;
@ -184,14 +186,24 @@ document.addEventListener('DOMContentLoaded', () => {
const response = await chrome.runtime.sendMessage({
action: 'saveSwipeFile',
data: {
negocio: result.negocios_id,
conteudo: content
negocio_id: result.negocios_id,
conteudo: content,
nome_autor: author,
link_autor: document.getElementById('authorProfileLink')?.value || '',
link_post: document.getElementById('postLink')?.value || ''
}
});
if (response.success) {
alert('Post salvo com sucesso!');
window.close();
// Construir URL do post
const postUrl = `https://launchr.com.br/posts/${result.negocios_nome}-${result.negocios_id}?tab=Swipe%20File`;
// Atualizar link no modal
document.getElementById('viewPostLink').href = postUrl;
// Mostrar modal
const successModal = new bootstrap.Modal(document.getElementById('successModal'));
successModal.show();
} else {
throw new Error(response.error || 'Erro ao salvar o post');
}
@ -202,6 +214,11 @@ document.addEventListener('DOMContentLoaded', () => {
});
});
// Fechar popup quando clicar em "Continuar"
document.querySelector('#successModal .btn-secondary')?.addEventListener('click', () => {
window.close();
});
// Gerenciar logout
const logoutButton = document.getElementById('logoutButton');
logoutButton?.addEventListener('click', () => {
@ -238,4 +255,43 @@ document.addEventListener('DOMContentLoaded', () => {
document.getElementById('content').value = result.currentPostData.content || '';
}
});
// Atualizar nome do negócio na interface
function updateNegocioDisplay() {
chrome.storage.local.get(['negocios_nome'], (result) => {
const negocioNomeElement = document.getElementById('negocioNome');
if (negocioNomeElement && result.negocios_nome) {
negocioNomeElement.textContent = result.negocios_nome;
}
});
}
// Atualizar interface após login bem-sucedido
loginForm?.addEventListener('submit', async (e) => {
e.preventDefault();
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;
chrome.runtime.sendMessage(
{
action: 'login',
data: { email, password }
},
(response) => {
if (response.success) {
showLoggedInSection();
updateNegocioDisplay(); // Atualizar nome do negócio
loadPostData();
} else {
alert(response.error || 'Erro ao fazer login');
}
}
);
});
// Atualizar nome do negócio ao carregar a página
if (document.getElementById('loggedInSection').classList.contains('d-none') === false) {
updateNegocioDisplay();
}
});