518 lines
30 KiB
HTML
518 lines
30 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>MVP - Minha Conta (v6 - Validação Ativa)</title>
|
|
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.12/cropper.min.css" rel="stylesheet">
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.12/cropper.min.js"></script>
|
|
|
|
<style>
|
|
/* Estilos gerais */
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
background-color: #f7f8fa;
|
|
color: #3d4852;
|
|
margin: 0;
|
|
padding: 20px;
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
.container {
|
|
background-color: #ffffff;
|
|
padding: 25px 30px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 4px 20px rgba(0,0,0,0.05);
|
|
border: 1px solid #eef0f2;
|
|
max-width: 720px;
|
|
width: 100%;
|
|
margin: 20px auto;
|
|
}
|
|
h1 {
|
|
color: #2c3e50;
|
|
text-align: center;
|
|
border-bottom: 1px solid #eef0f2;
|
|
padding-bottom: 15px;
|
|
margin-top: 0;
|
|
margin-bottom: 25px;
|
|
font-size: 1.8em;
|
|
font-weight: 600;
|
|
}
|
|
h2.section-title {
|
|
font-size: 1.2em;
|
|
color: #34495e;
|
|
margin-top: 30px;
|
|
margin-bottom: 18px;
|
|
border-bottom: 1px solid #eef0f2;
|
|
padding-bottom: 8px;
|
|
font-weight: 600;
|
|
}
|
|
.form-group { margin-bottom: 18px; position: relative; }
|
|
.form-row { display: flex; flex-wrap: wrap; gap: 18px; }
|
|
.form-row .form-group { flex: 1 1 180px; }
|
|
label { display: block; margin-bottom: 7px; font-weight: 600; color: #555; font-size: 0.9em; }
|
|
label .label-nudge { font-weight: 400; color: #3498db; font-size: 0.9em; margin-left: 8px; }
|
|
input[type="password"], input[type="text"], input[type="tel"] {
|
|
width: 100%;
|
|
padding: 10px 12px;
|
|
border: 1px solid #dce1e6;
|
|
border-radius: 5px;
|
|
box-sizing: border-box;
|
|
transition: border-color 0.3s, box-shadow 0.3s;
|
|
font-size: 0.95em;
|
|
}
|
|
input:focus { border-color: #3498db; box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.15); outline: none; }
|
|
input.error { border-color: #e74c3c; }
|
|
|
|
/* Layout Crachá */
|
|
.profile-header { display: flex; align-items: center; gap: 25px; margin-bottom: 25px; }
|
|
.profile-photo { text-align: center; }
|
|
#image_preview { width: 110px; height: 110px; border: 3px solid #f0f2f5; border-radius: 50%; object-fit: cover; cursor: pointer; transition: transform 0.2s, box-shadow 0.2s; }
|
|
#image_preview:hover { transform: scale(1.05); box-shadow: 0 0 15px rgba(0,0,0,0.1); }
|
|
.profile-info { flex: 1; }
|
|
.profile-info .form-row { gap: 15px; }
|
|
.info-display { margin-top: 10px; }
|
|
.info-display p { margin: 2px 0; color: #7f8c8d; font-size: 0.9em; }
|
|
.info-display p.email { font-size: 0.95em; color: #34495e; margin-bottom: 8px; }
|
|
.info-display p.email .sam-account { color: #7f8c8d; font-size: 0.9em; }
|
|
.info-display strong { color: #34495e; font-weight: 600; }
|
|
|
|
/* Estilos Específicos */
|
|
.whatsapp-checkbox { display: flex; align-items: center; margin-top: 8px; }
|
|
.whatsapp-checkbox input { margin-right: 8px; width: 16px; height: 16px; }
|
|
.whatsapp-checkbox label { margin-bottom: 0; font-weight: 400; font-size: 0.9em; }
|
|
.address-disclaimer { font-size: 0.85em; color: #6a7785; background-color: #f8f9fa; padding: 10px 12px; border-radius: 4px; border: 1px solid #e9ecef; margin-top: -10px; margin-bottom: 18px; }
|
|
.validation-nudge { display: none; padding: 12px; background-color: #fffbe6; border: 1px solid #ffe58f; border-radius: 5px; margin-top: 5px; font-size: 0.9em; color: #8a6d3b; align-items: center; justify-content: space-between; }
|
|
.validation-nudge.visible { display: flex; }
|
|
.validation-nudge-confirm { background: #ffe58f; border: none; color: #8a6d3b; padding: 4px 8px; border-radius: 4px; cursor: pointer; font-weight: bold; }
|
|
|
|
/* Animações e Botões */
|
|
button { width: 100%; padding: 12px; background-color: #3498db; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; font-weight: bold; margin-top: 20px; position: relative; transition: all 0.2s; overflow: hidden; box-shadow: 0 2px 4px rgba(0,0,0,0.08); }
|
|
button:hover:not(:disabled) { background-color: #2980b9; transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
|
|
button:disabled { cursor: wait; }
|
|
.button-content, .button-loader, .button-success-icon { transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out; }
|
|
.button-content { display: flex; justify-content: center; align-items: center; }
|
|
.button-loader { position: absolute; opacity: 0; width: 20px; height: 20px; border: 2px solid rgba(255, 255, 255, 0.5); border-top-color: #ffffff; border-radius: 50%; animation: spin 1s linear infinite; }
|
|
.button-success-icon { position: absolute; opacity: 0; font-size: 24px; line-height: 1; }
|
|
button.sending { background-color: #95a5a6; } button.sending .button-text, button.success .button-loader, button.success .button-text { opacity: 0; }
|
|
button.sending .button-loader, button.success .button-success-icon { opacity: 1; }
|
|
button.success { background-color: #27ae60; }
|
|
button.success .button-success-icon { transform: scale(1.2); }
|
|
@keyframes spin { to { transform: rotate(360deg); } }
|
|
.password-toggle { position: absolute; top: 50%; transform: translateY(-50%); right: 10px; cursor: pointer; width: 20px; height: 20px; }
|
|
.password-toggle svg { width:100%; height:100%; fill: none; stroke: #aaa; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
|
|
.strength-meter { height: 5px; background: #eee; border-radius: 5px; margin-top: 5px; } .strength-meter-fill { height: 100%; width: 0; border-radius: 5px; transition: width 0.3s, background-color 0.3s; }
|
|
.strength-text { font-size: 0.8em; text-align: right; margin-top: 2px; height: 1em; }
|
|
.error-message { color: #e74c3c; font-size: 0.85em; margin-top: 8px; min-height: 1.2em; display: none; opacity: 0; transition: opacity 0.3s ease-in-out; }
|
|
.error-message.visible { display: block; opacity: 1; }
|
|
|
|
/* Modal */
|
|
.modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); display: none; justify-content: center; align-items: center; z-index: 1000; }
|
|
.modal-content { background: #fff; padding: 20px; border-radius: 8px; width: 90%; max-width: 500px; }
|
|
.modal-cropper-container { height: 300px; margin-bottom: 15px; } .modal-controls { display: flex; justify-content: center; align-items: center; gap: 15px; margin-bottom: 15px; }
|
|
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; } .modal-btn { padding: 8px 16px; border-radius: 4px; border: 1px solid #ccc; cursor: pointer; }
|
|
.btn-confirm { background-color: #27ae60; color: white; border-color: #27ae60; }
|
|
#zoom-slider { width: 60%; }
|
|
|
|
/* Media Query para responsividade */
|
|
@media (max-width: 600px) {
|
|
.profile-header { flex-direction: column; }
|
|
.profile-info { width: 100%; }
|
|
.container { padding: 20px; }
|
|
h1 { font-size: 1.5em; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<form id="profile-form">
|
|
<h1>Minha Conta</h1>
|
|
|
|
<div class="profile-header">
|
|
<div class="profile-photo">
|
|
<img id="image_preview" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150' viewBox='0 0 24 24' fill='%23f0f0f1' stroke='%23ccc' stroke-width='1' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='8' r='4'%3E%3C/circle%3E%3Cpath d='M19 20v-1a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v1'%3E%3C/path%3E%3C/svg%3E" alt="Foto de perfil" title="Clique para alterar sua foto">
|
|
</div>
|
|
<div class="profile-info">
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="given_name">Nome</label>
|
|
<input type="text" id="given_name" name="GivenName" placeholder="Seu nome">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="surname">Sobrenome</label>
|
|
<input type="text" id="surname" name="Surname" placeholder="Seu sobrenome">
|
|
</div>
|
|
</div>
|
|
<div class="info-display">
|
|
<p class="email"><strong id="display_email"></strong> <span class="sam-account">(<span id="display_sam_account"></span>)</span></p>
|
|
<p id="display_title"></p>
|
|
<p id="display_department"></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2 class="section-title">Contato Corporativo</h2>
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="office_phone">Telefone Comercial</label>
|
|
<input type="tel" id="office_phone" name="OfficePhone" placeholder="+55 (21) 0000-0000">
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="mobile_phone">Celular <span class="label-nudge">Ajude o RH a te encontrar!</span></label>
|
|
<input type="tel" id="mobile_phone" name="MobilePhone" placeholder="+55 (21) 90000-0000">
|
|
<div class="whatsapp-checkbox">
|
|
<input type="checkbox" id="has_whatsapp" name="HasWhatsapp">
|
|
<label for="has_whatsapp">Este número tem WhatsApp</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2 class="section-title">Endereço Residencial</h2>
|
|
<p class="address-disclaimer">Estas informações são confidenciais e de uso exclusivo do departamento de RH para comunicações oficiais e envios.</p>
|
|
<div class="form-group">
|
|
<label for="street_address">Endereço (Rua, Av, etc)</label>
|
|
<input type="text" id="street_address" name="StreetAddress" placeholder="Ex: Rua Principal, 123">
|
|
</div>
|
|
<div class="form-row">
|
|
<div class="form-group" style="flex: 3 1 250px;">
|
|
<label for="city">Cidade</label>
|
|
<input type="text" id="city" name="City" placeholder="Sua cidade">
|
|
</div>
|
|
<div class="form-group" style="flex: 1 1 50px;">
|
|
<label for="state">UF</label>
|
|
<input type="text" id="state" name="State" placeholder="RJ">
|
|
</div>
|
|
<div class="form-group" style="flex: 2 1 120px;">
|
|
<label for="postal_code">CEP</label>
|
|
<input type="text" id="postal_code" name="PostalCode" placeholder="00000-000">
|
|
</div>
|
|
</div>
|
|
<div id="address-validation-nudge" class="validation-nudge">
|
|
<span><strong>Atenção:</strong> Seu endereço não é atualizado há mais de um ano. As informações ainda estão corretas?</span>
|
|
<button type="button" id="confirm-address-btn" class="validation-nudge-confirm">✔ Sim, está correto</button>
|
|
</div>
|
|
|
|
<h2 class="section-title">Segurança</h2>
|
|
<div class="form-group">
|
|
<label for="old_password">Senha Atual (Obrigatória para salvar)</label>
|
|
<div style="position: relative;">
|
|
<input type="password" id="old_password" name="OldPassword" placeholder="••••••••" required>
|
|
<span class="password-toggle" title="Exibir/Ocultar Senha">
|
|
<svg class="eye-visible" style="display:none;" viewBox="0 0 24 24"><path d="M1,12 C1,12 5,4 12,4 C19,4 23,12 23,12 C23,12 19,20 12,20 C5,20 1,12 1,12 Z"></path><circle cx="12" cy="12" r="3"></circle></svg>
|
|
<svg class="eye-hidden" viewBox="0 0 24 24"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="new_password">Nova Senha</label>
|
|
<div style="position: relative;">
|
|
<input type="password" id="new_password" name="NewPassword" placeholder="Deixe em branco para não alterar">
|
|
<span class="password-toggle" title="Exibir/Ocultar Senha">
|
|
<svg class="eye-visible" style="display:none;" viewBox="0 0 24 24"><path d="M1,12 C1,12 5,4 12,4 C19,4 23,12 23,12 C23,12 19,20 12,20 C5,20 1,12 1,12 Z"></path><circle cx="12" cy="12" r="3"></circle></svg>
|
|
<svg class="eye-hidden" viewBox="0 0 24 24"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>
|
|
</span>
|
|
</div>
|
|
<div id="password-error-message" class="error-message"></div>
|
|
<div class="strength-meter"><div id="strength-fill" class="strength-meter-fill"></div></div>
|
|
<div id="strength-text" class="strength-text"></div>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="confirm_password">Confirmar Nova Senha</label>
|
|
<div style="position: relative;">
|
|
<input type="password" id="confirm_password" name="ConfirmNewPassword" placeholder="Repita a nova senha">
|
|
<span class="password-toggle" title="Exibir/Ocultar Senha">
|
|
<svg class="eye-visible" style="display:none;" viewBox="0 0 24 24"><path d="M1,12 C1,12 5,4 12,4 C19,4 23,12 23,12 C23,12 19,20 12,20 C5,20 1,12 1,12 Z"></path><circle cx="12" cy="12" r="3"></circle></svg>
|
|
<svg class="eye-hidden" viewBox="0 0 24 24"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<button type="submit" id="submit-button">
|
|
<span class="button-content">
|
|
<span class="button-text">Salvar Alterações</span>
|
|
<span class="button-loader"></span>
|
|
<span class="button-success-icon">✓</span>
|
|
</span>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div id="modal" class="modal-overlay"><div class="modal-content"><h3>Editar Foto de Perfil</h3><div class="modal-cropper-container"><img id="image_to_crop"></div><div class="modal-controls"><span>Zoom</span><input type="range" id="zoom-slider"></div><div class="modal-actions"><button type="button" id="cancel-crop" class="modal-btn">Cancelar</button><button type="button" id="confirm-crop" class="modal-btn btn-confirm">Confirmar</button></div></div></div>
|
|
<input type="file" id="profile_image_input" accept="image/png, image/jpeg" style="display: none;">
|
|
|
|
<script>
|
|
// --- Escopo Global ---
|
|
const profileForm = document.getElementById('profile-form');
|
|
const imagePreview = document.getElementById('image_preview');
|
|
const imageInput = document.getElementById('profile_image_input');
|
|
const submitButton = document.getElementById('submit-button');
|
|
const newPasswordInput = document.getElementById('new_password');
|
|
const confirmPasswordInput = document.getElementById('confirm_password');
|
|
const strengthFill = document.getElementById('strength-fill');
|
|
const strengthText = document.getElementById('strength-text');
|
|
const passwordErrorMessage = document.getElementById('password-error-message');
|
|
const modal = document.getElementById('modal');
|
|
const imageToCrop = document.getElementById('image_to_crop');
|
|
const zoomSlider = document.getElementById('zoom-slider');
|
|
let croppedImageData = null;
|
|
let cropper;
|
|
|
|
// --- Funções de Validação e Formatação ---
|
|
const sanitizeName = (event) => {
|
|
// Permite letras, espaços e acentos comuns em português. Remove o resto.
|
|
event.target.value = event.target.value.replace(/[^a-zA-Z\sÀ-ú]/g, '');
|
|
};
|
|
|
|
const formatPhoneNumber = (event, type = 'any') => {
|
|
let value = event.target.value.replace(/\D/g, '');
|
|
if (value.startsWith('55')) {
|
|
value = value.substring(2);
|
|
}
|
|
|
|
let formatted = '+55';
|
|
if (value.length > 0) {
|
|
formatted += ` (${value.substring(0, 2)}`;
|
|
}
|
|
if (value.length > 2) {
|
|
const numPart = value.substring(2);
|
|
let limit = type === 'mobile' ? 9 : (numPart.length === 9 ? 9 : 8);
|
|
|
|
if (numPart.length > (limit === 9 ? 5 : 4)) {
|
|
formatted += `) ${numPart.substring(0, limit - 4)}-${numPart.substring(limit-4, limit)}`;
|
|
} else {
|
|
formatted += `) ${numPart}`;
|
|
}
|
|
}
|
|
event.target.value = formatted;
|
|
};
|
|
|
|
|
|
// --- Inicialização e Carregamento de Dados ---
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
// Dados mocados para simulação
|
|
const userData = {
|
|
GivenName: "Ana", Surname: "Silva", UserPrincipalName: "ana.silva@grupopralog.com.br", SamAccountName: "ana.silva",
|
|
Title: "Analista Financeiro Sênior", Department: "Financeiro", OfficePhone: "+552133445566", MobilePhone: "+5521999998888",
|
|
StreetAddress: "Rua Principal, 123", City: "Rio de Janeiro", State: "RJ", PostalCode: "22000-000", HasWhatsapp: true,
|
|
};
|
|
|
|
// Populando o formulário
|
|
document.getElementById('given_name').value = userData.GivenName;
|
|
document.getElementById('surname').value = userData.Surname;
|
|
document.getElementById('display_email').textContent = userData.UserPrincipalName;
|
|
document.getElementById('display_sam_account').textContent = userData.SamAccountName;
|
|
document.getElementById('display_title').textContent = userData.Title;
|
|
document.getElementById('display_department').textContent = userData.Department;
|
|
document.getElementById('office_phone').value = userData.OfficePhone;
|
|
document.getElementById('mobile_phone').value = userData.MobilePhone;
|
|
document.getElementById('has_whatsapp').checked = userData.HasWhatsapp;
|
|
document.getElementById('street_address').value = userData.StreetAddress;
|
|
document.getElementById('city').value = userData.City;
|
|
document.getElementById('state').value = userData.State;
|
|
document.getElementById('postal_code').value = userData.PostalCode;
|
|
|
|
// Simula formatação inicial dos telefones
|
|
formatPhoneNumber({ target: document.getElementById('office_phone') }, 'any');
|
|
formatPhoneNumber({ target: document.getElementById('mobile_phone') }, 'mobile');
|
|
console.log(`[${new Date().toLocaleTimeString()}] DADOS DO USUÁRIO CARREGADOS (MOCK).`);
|
|
|
|
// Lógica do Nudge de Endereço
|
|
const addressNudge = document.getElementById('address-validation-nudge');
|
|
if (sessionStorage.getItem('addressConfirmed') !== 'true' && Math.random() > 0.5) {
|
|
addressNudge.classList.add('visible');
|
|
}
|
|
document.getElementById('confirm-address-btn').addEventListener('click', () => {
|
|
addressNudge.classList.remove('visible');
|
|
sessionStorage.setItem('addressConfirmed', 'true');
|
|
});
|
|
});
|
|
|
|
// --- Event Listeners ---
|
|
document.getElementById('given_name').addEventListener('input', sanitizeName);
|
|
document.getElementById('surname').addEventListener('input', sanitizeName);
|
|
document.getElementById('office_phone').addEventListener('input', (e) => formatPhoneNumber(e, 'any'));
|
|
document.getElementById('mobile_phone').addEventListener('input', (e) => formatPhoneNumber(e, 'mobile'));
|
|
|
|
imagePreview.addEventListener('click', () => imageInput.click());
|
|
imageInput.addEventListener('change', (e) => {
|
|
if (e.target.files && e.target.files[0]) {
|
|
const reader = new FileReader();
|
|
reader.onload = (event) => {
|
|
imageToCrop.src = event.target.result;
|
|
modal.style.display = 'flex';
|
|
if(cropper) cropper.destroy();
|
|
cropper = new Cropper(imageToCrop, {
|
|
aspectRatio: 1, viewMode: 1, dragMode: 'move', autoCropArea: 1,
|
|
cropBoxMovable: false, cropBoxResizable: false, background: false,
|
|
ready: function() {
|
|
const canvasData = cropper.getCanvasData();
|
|
const minZoomRatio = canvasData.width / canvasData.naturalWidth;
|
|
zoomSlider.min = minZoomRatio; zoomSlider.max = minZoomRatio * 3;
|
|
zoomSlider.step = (zoomSlider.max - minZoomRatio) / 100;
|
|
zoomSlider.value = minZoomRatio;
|
|
cropper.zoomTo(minZoomRatio);
|
|
}
|
|
});
|
|
};
|
|
reader.readAsDataURL(e.target.files[0]);
|
|
}
|
|
});
|
|
|
|
zoomSlider.addEventListener('input', (e) => cropper.zoomTo(e.target.value));
|
|
document.getElementById('cancel-crop').addEventListener('click', () => { modal.style.display = 'none'; imageInput.value = ''; });
|
|
document.getElementById('confirm-crop').addEventListener('click', () => {
|
|
const canvas = cropper.getCroppedCanvas({ width: 256, height: 256 });
|
|
imagePreview.src = canvas.toDataURL('image/jpeg');
|
|
canvas.toBlob(blob => { croppedImageData = blob; }, 'image/jpeg');
|
|
modal.style.display = 'none';
|
|
});
|
|
|
|
document.querySelectorAll('.password-toggle').forEach(toggle => {
|
|
toggle.addEventListener('click', () => {
|
|
const passwordField = toggle.parentElement.querySelector('input');
|
|
const eyeVisible = toggle.querySelector('.eye-visible');
|
|
const eyeHidden = toggle.querySelector('.eye-hidden');
|
|
passwordField.type = passwordField.type === 'password' ? 'text' : 'password';
|
|
eyeVisible.style.display = passwordField.type === 'text' ? 'block' : 'none';
|
|
eyeHidden.style.display = passwordField.type === 'text' ? 'none' : 'block';
|
|
});
|
|
});
|
|
|
|
newPasswordInput.addEventListener('input', () => {
|
|
newPasswordInput.classList.remove('error');
|
|
passwordErrorMessage.classList.remove('visible');
|
|
confirmPasswordInput.value = '';
|
|
|
|
const pass = newPasswordInput.value; let score = -1; let text = ''; let color = '';
|
|
if (pass.length > 0 && pass.length < 8) { score = 0; text = 'Muito Fraca'; color = '#e74c3c'; }
|
|
else if (pass.length >= 8) {
|
|
score = 1;
|
|
if (/[a-z]/.test(pass) && /[A-Z]/.test(pass)) score++;
|
|
if (/\d/.test(pass)) score++;
|
|
if (/[^A-Za-z0-9]/.test(pass)) score++;
|
|
|
|
const strengthMap = { 1: ['Fraca', '#e74c3c'], 2: ['Média', '#f39c12'], 3: ['Forte', '#2ecc71'], 4: ['Muito Forte', '#27ae60'] };
|
|
[text, color] = strengthMap[score] || ['', ''];
|
|
}
|
|
strengthFill.style.width = score === -1 ? '0' : ((score / 4) * 100 + '%');
|
|
strengthFill.style.backgroundColor = color;
|
|
strengthText.textContent = text;
|
|
});
|
|
|
|
// --- Lógica de Submissão do Formulário ---
|
|
const mockCheckPwnedPassword = (password) => {
|
|
return new Promise(resolve => {
|
|
console.log(`%c[${new Date().toLocaleTimeString()}] VERIFICANDO SENHA EM BANCO DE DADOS DE VAZAMENTOS...`, 'color: #f39c12;');
|
|
setTimeout(() => {
|
|
const pwnedPasswords = ['123mudar', 'senha@123'];
|
|
if (pwnedPasswords.includes(password.toLowerCase())) {
|
|
resolve({ pwned: true, count: Math.floor(Math.random() * (10000 - 500) + 500) });
|
|
} else {
|
|
resolve({ pwned: false });
|
|
}
|
|
}, 1500);
|
|
});
|
|
};
|
|
|
|
const handlePasswordError = (message) => {
|
|
console.error(`VALIDAÇÃO FALHOU: ${message}`);
|
|
newPasswordInput.classList.add('error');
|
|
passwordErrorMessage.textContent = message;
|
|
passwordErrorMessage.classList.add('visible');
|
|
newPasswordInput.focus();
|
|
newPasswordInput.value = '';
|
|
confirmPasswordInput.value = '';
|
|
strengthFill.style.width = '0';
|
|
strengthText.textContent = '';
|
|
submitButton.classList.remove('sending');
|
|
submitButton.disabled = false;
|
|
};
|
|
|
|
profileForm.addEventListener('submit', async (event) => {
|
|
event.preventDefault();
|
|
|
|
newPasswordInput.classList.remove('error');
|
|
passwordErrorMessage.classList.remove('visible');
|
|
|
|
const oldPassword = document.getElementById('old_password').value;
|
|
const newPassword = newPasswordInput.value;
|
|
const confirmPassword = confirmPasswordInput.value;
|
|
|
|
if (!oldPassword) {
|
|
alert('A Senha Atual é obrigatória para salvar qualquer alteração.');
|
|
document.getElementById('old_password').focus();
|
|
return;
|
|
}
|
|
|
|
if (newPassword) {
|
|
if (newPassword.length < 8) { handlePasswordError("A nova senha deve ter no mínimo 8 caracteres."); return; }
|
|
if (newPassword !== confirmPassword) { handlePasswordError("A nova senha e a confirmação não são idênticas."); return; }
|
|
if (newPassword === oldPassword) { handlePasswordError("A nova senha não pode ser igual à senha atual."); return; }
|
|
}
|
|
|
|
submitButton.classList.add('sending'); submitButton.disabled = true;
|
|
|
|
if (newPassword) {
|
|
const pwnedResult = await mockCheckPwnedPassword(newPassword);
|
|
if (pwnedResult.pwned) {
|
|
handlePasswordError(`Esta senha é insegura, pois foi encontrada em ${pwnedResult.count.toLocaleString('pt-BR')} vazamentos de dados. Por favor, escolha outra.`);
|
|
return;
|
|
}
|
|
console.info(`%c[SUCESSO] Verificação de segurança concluída. A senha não foi encontrada em vazamentos.`, 'color: green');
|
|
}
|
|
|
|
console.log(`%c[${new Date().toLocaleTimeString()}] INICIANDO ENVIO PARA O BACKEND...`, 'color: #3498db; font-weight: bold;');
|
|
|
|
const profileData = {
|
|
GivenName: document.getElementById('given_name').value, Surname: document.getElementById('surname').value,
|
|
OfficePhone: document.getElementById('office_phone').value.replace(/\D/g, ''), MobilePhone: document.getElementById('mobile_phone').value.replace(/\D/g, ''),
|
|
HasWhatsapp: document.getElementById('has_whatsapp').checked, StreetAddress: document.getElementById('street_address').value,
|
|
City: document.getElementById('city').value, State: document.getElementById('state').value, PostalCode: document.getElementById('postal_code').value.replace(/\D/g, '')
|
|
};
|
|
|
|
setTimeout(() => {
|
|
let actions = [ { "Ação": "Atualização de Dados do Perfil", "Script": "set-aduser-attributes.ps1" } ];
|
|
if (croppedImageData) {
|
|
actions.push({ "Ação": "Atualização de Foto de Perfil", "Detalhe": `cropped_image.jpeg (${Math.round(croppedImageData.size / 1024)} KB)`, "Script": "set-user-profilephoto.ps1" });
|
|
}
|
|
if (newPassword) {
|
|
actions.push({ "Ação": "Alteração de Senha", "Validação": "SUCESSO (simulado)", "Script": "set-user-password.ps1" });
|
|
}
|
|
|
|
console.group(`%c[${new Date().toLocaleTimeString()}] RESPOSTA DO BACKEND (SIMULADA)`, 'color: #27ae60; font-weight: bold;');
|
|
console.log("DESTINO: API de Atualização de Perfil");
|
|
|
|
console.group("PAYLOAD DE DADOS ENVIADO (higienizado)");
|
|
console.table(profileData);
|
|
console.groupEnd();
|
|
|
|
console.log("AÇÕES EXECUTADAS:");
|
|
console.table(actions);
|
|
console.groupEnd();
|
|
|
|
submitButton.classList.remove('sending'); submitButton.classList.add('success');
|
|
|
|
// Após salvar, esconde o nudge de endereço e marca como confirmado na sessão
|
|
const addressNudge = document.getElementById('address-validation-nudge');
|
|
if (addressNudge.classList.contains('visible')) {
|
|
addressNudge.classList.remove('visible');
|
|
sessionStorage.setItem('addressConfirmed', 'true');
|
|
}
|
|
|
|
setTimeout(() => {
|
|
submitButton.classList.remove('success'); submitButton.disabled = false;
|
|
|
|
document.getElementById('old_password').value = '';
|
|
document.getElementById('new_password').value = '';
|
|
document.getElementById('confirm_password').value = '';
|
|
strengthFill.style.width = '0';
|
|
strengthText.textContent = '';
|
|
|
|
console.log(`%c[${new Date().toLocaleTimeString()}] INTERFACE PRONTA PARA NOVAS ALTERAÇÕES.`, 'color: #9b59b6;');
|
|
}, 1800);
|
|
}, 1500);
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html> |