442 lines
15 KiB
HTML
442 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="pt-BR">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Instalação - Dental Image Server</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
min-height: 100vh;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 20px;
|
|
}
|
|
|
|
.install-container {
|
|
background: white;
|
|
border-radius: 20px;
|
|
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
|
|
max-width: 600px;
|
|
width: 100%;
|
|
padding: 40px;
|
|
}
|
|
|
|
h1 {
|
|
color: #333;
|
|
margin-bottom: 10px;
|
|
font-size: 28px;
|
|
}
|
|
|
|
.subtitle {
|
|
color: #666;
|
|
margin-bottom: 30px;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.step {
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
.step-title {
|
|
font-weight: 600;
|
|
color: #667eea;
|
|
margin-bottom: 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.step-number {
|
|
background: #667eea;
|
|
color: white;
|
|
width: 24px;
|
|
height: 24px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 12px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
label {
|
|
display: block;
|
|
margin-bottom: 8px;
|
|
color: #333;
|
|
font-weight: 500;
|
|
font-size: 14px;
|
|
}
|
|
|
|
input, select {
|
|
width: 100%;
|
|
padding: 12px;
|
|
border: 2px solid #e0e0e0;
|
|
border-radius: 8px;
|
|
font-size: 14px;
|
|
transition: border-color 0.3s;
|
|
}
|
|
|
|
input:focus, select:focus {
|
|
outline: none;
|
|
border-color: #667eea;
|
|
}
|
|
|
|
.form-help {
|
|
font-size: 12px;
|
|
color: #999;
|
|
margin-top: 5px;
|
|
}
|
|
|
|
.btn {
|
|
width: 100%;
|
|
padding: 14px;
|
|
background: #667eea;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 8px;
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: background 0.3s;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.btn:hover {
|
|
background: #5568d3;
|
|
}
|
|
|
|
.btn:disabled {
|
|
background: #ccc;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.alert {
|
|
padding: 12px;
|
|
border-radius: 8px;
|
|
margin-bottom: 20px;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.alert-success {
|
|
background: #d4edda;
|
|
color: #155724;
|
|
border: 1px solid #c3e6cb;
|
|
}
|
|
|
|
.alert-error {
|
|
background: #f8d7da;
|
|
color: #721c24;
|
|
border: 1px solid #f5c6cb;
|
|
}
|
|
|
|
.alert-info {
|
|
background: #d1ecf1;
|
|
color: #0c5460;
|
|
border: 1px solid #bee5eb;
|
|
}
|
|
|
|
.loading {
|
|
display: none;
|
|
text-align: center;
|
|
padding: 20px;
|
|
}
|
|
|
|
.spinner {
|
|
border: 3px solid #f3f3f3;
|
|
border-top: 3px solid #667eea;
|
|
border-radius: 50%;
|
|
width: 40px;
|
|
height: 40px;
|
|
animation: spin 1s linear infinite;
|
|
margin: 0 auto 10px;
|
|
}
|
|
|
|
@keyframes spin {
|
|
0% { transform: rotate(0deg); }
|
|
100% { transform: rotate(360deg); }
|
|
}
|
|
|
|
.success-message {
|
|
text-align: center;
|
|
padding: 20px;
|
|
display: none;
|
|
}
|
|
|
|
.success-icon {
|
|
font-size: 64px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.check-status {
|
|
padding: 15px;
|
|
background: #f8f9fa;
|
|
border-radius: 8px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.status-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
padding: 8px 0;
|
|
border-bottom: 1px solid #e0e0e0;
|
|
}
|
|
|
|
.status-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.status-ok {
|
|
color: #28a745;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.status-fail {
|
|
color: #dc3545;
|
|
font-weight: 600;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="install-container">
|
|
<h1>🦷 Instalação do Sistema</h1>
|
|
<p class="subtitle">Configure o banco de dados e crie o usuário administrador</p>
|
|
|
|
<div id="statusCheck" class="check-status">
|
|
<div class="status-item">
|
|
<span>Verificando status da instalação...</span>
|
|
<span id="statusLoading" class="spinner" style="width: 16px; height: 16px; display: inline-block;"></span>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="alertContainer"></div>
|
|
|
|
<div id="installForm">
|
|
<div class="step">
|
|
<div class="step-title">
|
|
<span class="step-number">1</span>
|
|
<span>Configuração do Banco de Dados</span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Host MySQL</label>
|
|
<input type="text" id="dbHost" value="localhost" placeholder="localhost">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Porta MySQL</label>
|
|
<input type="number" id="dbPort" value="3306" placeholder="3306">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Nome do Banco</label>
|
|
<input type="text" id="dbName" value="dental_images" placeholder="dental_images">
|
|
<div class="form-help">O banco será criado automaticamente se não existir</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Usuário MySQL</label>
|
|
<input type="text" id="dbUser" value="root" placeholder="root">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Senha MySQL</label>
|
|
<input type="password" id="dbPassword" placeholder="Digite a senha">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="step">
|
|
<div class="step-title">
|
|
<span class="step-number">2</span>
|
|
<span>Usuário Administrador</span>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Nome de Usuário</label>
|
|
<input type="text" id="adminUsername" value="rcesar" placeholder="rcesar">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Email</label>
|
|
<input type="email" id="adminEmail" value="rcesar@rcesar.com" placeholder="admin@example.com">
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Senha</label>
|
|
<input type="password" id="adminPassword" value="Rc362514" placeholder="Digite uma senha segura">
|
|
<div class="form-help">Mínimo de 8 caracteres</div>
|
|
</div>
|
|
</div>
|
|
|
|
<button id="installBtn" class="btn" onclick="runInstallation()">
|
|
▶ Iniciar Instalação
|
|
</button>
|
|
</div>
|
|
|
|
<div id="loading" class="loading">
|
|
<div class="spinner"></div>
|
|
<p>Instalando... Por favor aguarde.</p>
|
|
</div>
|
|
|
|
<div id="successMessage" class="success-message">
|
|
<div class="success-icon">✅</div>
|
|
<h2>Instalação Concluída!</h2>
|
|
<p>O sistema foi configurado com sucesso.</p>
|
|
<button class="btn" onclick="window.location.href='/login'" style="margin-top: 20px;">
|
|
Ir para Login
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Verificar status ao carregar
|
|
async function checkStatus() {
|
|
try {
|
|
const response = await fetch('/api/install/status');
|
|
const data = await response.json();
|
|
|
|
const statusHtml = `
|
|
<div class="status-item">
|
|
<span>Arquivo de instalação (.installed)</span>
|
|
<span class="${data.installed ? 'status-ok' : 'status-fail'}">
|
|
${data.installed ? '✓ OK' : '✗ Não instalado'}
|
|
</span>
|
|
</div>
|
|
<div class="status-item">
|
|
<span>Arquivo de configuração (.env)</span>
|
|
<span class="${data.hasEnvFile ? 'status-ok' : 'status-fail'}">
|
|
${data.hasEnvFile ? '✓ OK' : '✗ Não configurado'}
|
|
</span>
|
|
</div>
|
|
<div class="status-item">
|
|
<span>Banco de dados</span>
|
|
<span class="${data.databaseExists ? 'status-ok' : 'status-fail'}">
|
|
${data.databaseExists ? '✓ Conectado' : '✗ Não configurado'}
|
|
</span>
|
|
</div>
|
|
<div class="status-item">
|
|
<span>Usuário admin</span>
|
|
<span class="${data.userExists ? 'status-ok' : 'status-fail'}">
|
|
${data.userExists ? '✓ Existe' : '✗ Não existe'}
|
|
</span>
|
|
</div>
|
|
`;
|
|
|
|
document.getElementById('statusCheck').innerHTML = statusHtml;
|
|
|
|
if (data.installed && data.databaseExists && data.userExists) {
|
|
showAlert('Sistema já está instalado!', 'success');
|
|
document.getElementById('installForm').style.display = 'none';
|
|
document.getElementById('successMessage').style.display = 'block';
|
|
}
|
|
} catch (error) {
|
|
console.error('Erro ao verificar status:', error);
|
|
}
|
|
}
|
|
|
|
async function runInstallation() {
|
|
const btn = document.getElementById('installBtn');
|
|
const form = document.getElementById('installForm');
|
|
const loading = document.getElementById('loading');
|
|
const success = document.getElementById('successMessage');
|
|
|
|
// Coletar dados
|
|
const installData = {
|
|
db: {
|
|
host: document.getElementById('dbHost').value.trim(),
|
|
port: parseInt(document.getElementById('dbPort').value) || 3306,
|
|
name: document.getElementById('dbName').value.trim(),
|
|
user: document.getElementById('dbUser').value.trim(),
|
|
password: document.getElementById('dbPassword').value
|
|
},
|
|
admin: {
|
|
username: document.getElementById('adminUsername').value.trim(),
|
|
email: document.getElementById('adminEmail').value.trim(),
|
|
password: document.getElementById('adminPassword').value
|
|
}
|
|
};
|
|
|
|
// Validações
|
|
if (!installData.db.host || !installData.db.name || !installData.db.user) {
|
|
showAlert('Preencha todos os campos do banco de dados!', 'error');
|
|
return;
|
|
}
|
|
|
|
if (!installData.admin.username || !installData.admin.email || !installData.admin.password) {
|
|
showAlert('Preencha todos os campos do administrador!', 'error');
|
|
return;
|
|
}
|
|
|
|
if (installData.admin.password.length < 8) {
|
|
showAlert('A senha deve ter no mínimo 8 caracteres!', 'error');
|
|
return;
|
|
}
|
|
|
|
if (!installData.admin.email.includes('@')) {
|
|
showAlert('Email inválido!', 'error');
|
|
return;
|
|
}
|
|
|
|
// Desabilitar botão
|
|
btn.disabled = true;
|
|
btn.textContent = 'Instalando...';
|
|
|
|
// Mostrar loading
|
|
form.style.display = 'none';
|
|
loading.style.display = 'block';
|
|
|
|
try {
|
|
const response = await fetch('/api/install', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(installData)
|
|
});
|
|
|
|
const result = await response.json();
|
|
|
|
if (result.success) {
|
|
loading.style.display = 'none';
|
|
success.style.display = 'block';
|
|
showAlert('Instalação concluída com sucesso! Você será redirecionado...', 'success');
|
|
|
|
// Aguardar e redirecionar
|
|
setTimeout(() => {
|
|
window.location.href = '/login';
|
|
}, 2000);
|
|
} else {
|
|
loading.style.display = 'none';
|
|
form.style.display = 'block';
|
|
btn.disabled = false;
|
|
btn.textContent = '▶ Iniciar Instalação';
|
|
showAlert(result.error || 'Erro na instalação. Verifique os dados e tente novamente.', 'error');
|
|
}
|
|
} catch (error) {
|
|
loading.style.display = 'none';
|
|
form.style.display = 'block';
|
|
btn.disabled = false;
|
|
btn.textContent = '▶ Iniciar Instalação';
|
|
showAlert('Erro ao conectar com o servidor: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
function showAlert(message, type) {
|
|
const container = document.getElementById('alertContainer');
|
|
container.innerHTML = `<div class="alert alert-${type}">${message}</div>`;
|
|
setTimeout(() => {
|
|
container.innerHTML = '';
|
|
}, 5000);
|
|
}
|
|
|
|
// Iniciar verificação
|
|
checkStatus();
|
|
</script>
|
|
</body>
|
|
</html>
|
|
|