add tag analytics

This commit is contained in:
David Itehua Xalamihua 2025-04-28 09:11:39 -06:00
parent 34b3840d15
commit 54a7271263
31 changed files with 883 additions and 486 deletions

View File

@ -1,99 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>
{% block title %}{{ title | default('FORMHä') }}{% endblock %}
</title>
<!-- {# i bootstrap #} -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<!-- {# icons #}} -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<!-- {# f bootstrap #} -->
{% block css %}
{% endblock %}
<!-- {# i navbar css #} -->
<link rel="stylesheet" href="{{url_for('static', filename='template/tmp.css')}}">
<!-- {# navbar #} -->
<link rel="stylesheet" href="{{url_for('static', filename='template/navbar.css')}}">
<!-- {# f navbar css #} -->
<!-- {# i notify css #} -->
<!-- {# doc: https://github.com/simple-notify/simple-notify?tab=readme-ov-file #} -->
<!-- CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/simple-notify/dist/simple-notify.css" />
<!-- JS -->
<script src="https://cdn.jsdelivr.net/npm/simple-notify/dist/simple-notify.min.js"></script>
<!-- {# f notify js #} -->
</head>
<!-- <body> -->
<body>
{% block navbar %}
<!-- {# {% include 'comps/navbar_usr.html' %} #} -->
<nav class="navbar navbar-expand-lg bg-body-tertiary navbar-custom">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('home') }}">
{% include 'comps/formha.html' %}
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0 effect-3">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-person-circle"></i> {{nombre}}
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#"><i class="bi bi-file-earmark-person-fill"></i> Usuarios</a></li>
<li><hr class="dropdown-divider"></li>
<!-- <li><a class="dropdown-item" href="#">Something else here</a></li> -->
<li>
<a class="dropdown-item" href="{{ url_for('logout') }}">
<i class="bi bi-door-open-fill"></i> Logout
</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
{% endblock navbar %}
<!-- <main> -->
<main>
{% block body %}
{% endblock body %}
</main>
{% include 'comps/footer.html' %}
<!-- {# i bootstrap js #} -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
<!-- {# f bootstrap js #} -->
{% block js %}
{% include 'comps/notification.html' %}
{% if f_mnsj %}
<script>
simpleNotification("{{ f_mnsj.title }}", "{{ f_mnsj.body }}", "{{ f_mnsj.typeAlert }}");
</script>
{% endif %}
{% endblock js %}
</body>
</html>

View File

@ -1,24 +1,25 @@
/* Smartphones (hasta 767px) */
@media (max-width: 767px) {
/* body{ background-color: black; } */
/* main{ background-color: black; } */
}
/* Tablets (768px - 1023px) */
@media (min-width: 768px) and (max-width: 1023px) {
/* body{ background-color: pink; } */
/* main{ background-color: pink; } */
}
/* Laptops (1024px - 1439px) */
/* Laptops (1024px - 1439px) monitores resulición baja */
@media (min-width: 1024px) and (max-width: 1439px) {
/* body{ background-color: purple; } */
/* main{ background-color: purple; } */
}
/* PCs de escritorio (1440px - 1919px) */
/* PCs de escritorio (1440px - 1919px) macbook */
@media (min-width: 1440px) and (max-width: 1919px) {
/* body{ background-color: greenyellow; } */
/* main{ background-color: greenyellow; } */
}
/* Pantallas Ultrawide (1920px en adelante) */
@media (min-width: 1920px) {
/* body{ background-color: red; } */
/* main{ background-color: red; } */
}

View File

@ -37,6 +37,7 @@ export email_sender="systems.dix.dev@gmail.com"
export pswd_formha="qcpg picq gnxp kwtx"
export jwt_secret_key="pswd_2025_formha_s3cr3t_k3i_4pp"
export email_secret_key="FoRmHä_z0z5"
export login_url='http://127.0.0.1:8089/login'
export forma_db='{
"host":"db_s", "port":5432, "database":"formha", "user":"postgres", "password":"Shala55951254"
}';
@ -60,21 +61,3 @@ sudo systemctl restart apache2
#########################################################################################################
# variables de entorno DIX
#########################################################################################################
export tac_db='{
"host":"db_s",
"port":5432,
"database":"tac_reclutamiento",
"user":"postgres",
"password":"Shala55951254"
}';
export n_server="Server No. 1";
export ip_device=$(ifconfig | grep -A 1 '^[a-zA-Z]' | grep 'inet ' | head -n 1 | awk '{print $2}')

14
main.py
View File

@ -24,6 +24,8 @@ app = Flask(__name__)
bcrypt = Bcrypt(app)
# csrf = CSRFProtect(app)
url_login = os.getenv("login_url")
email_sender = os.getenv("email_sender")
email_pswd = os.getenv("pswd_formha")
# lst_email_to = ["davidix1991@gmail.com", "davicho1991@live.com"]
@ -265,10 +267,16 @@ def contact():
# Configurar y enviar email asíncrono
msg = Message( "Subject, una persona busca asesoria", sender=email_sender, recipients=lst_email_to() )
msg.html ="""
msg.html =f"""
<h1>Nuevo contacto recibido</h1>
<p><trong>Fecha: </strong> {}</p><p><strong>Hora:</strong> {}</p> <p><strong>Nombre:</strong> {} {}</p> <p><strong>Email:</strong> {}</p> <p><strong>Teléfono:</strong> {}</p> <p><strong>Mensaje:</strong> {}</p> <a href="http://127.0.0.1:8089/login" target='_blank'>Iniciar Sesión</a>
""".format(fecha, hora, form.nombre.data, form.apellido.data, form.email.data, form.num_tel.data, form.tipo_req.data)
<p><trong>Fecha: </strong> {fecha}</p>
<p><strong>Hora:</strong> {hora}</p>
<p><strong>Nombre:</strong> {form.nombre.data} {form.apellido.data}</p>
<p><strong>Email:</strong> {form.email.data}</p>
<p><strong>Teléfono:</strong> {form.num_tel.data}</p>
<p><strong>Mensaje:</strong> {form.tipo_req.data}</p>
<p><a href="{url_login}" target='_blank'>Iniciar Sesión</a></p>
"""
# Enviar en segundo plano
thr = Thread( target=send_async_email, args=(current_app._get_current_object(), msg) )

View File

@ -100,23 +100,22 @@
/* MEDIA QUERIES - RESPONSIVE DESIGN */
/* ============================================ */
main {
place-items: center;
}
/* Smartphones (hasta 767px) */
@media (max-width: 767px) {
main {
width: 95vw;
margin: 1em auto;
min-height: 100vh;
margin-top: 1em;
margin-bottom: 1em;
}
.expanding-panels {
grid-template-rows: repeat(4, 1fr);
row-gap: 2em;
.panel {
height: 45vh;
height: 70vh;
}
}
}
@ -125,18 +124,13 @@
@media (min-width: 768px) and (max-width: 1023px) {
main {
width: 90vw;
margin: auto;
min-height: 85vh;
margin-top: 1em;
margin-bottom: 1em;
min-height: 130vh;
}
.expanding-panels {
grid-template-columns: repeat(2, 1fr);
.panel {
height: 45vh;
height: 64vh;
}
}
}
@ -145,18 +139,13 @@
@media (min-width: 1024px) and (max-width: 1439px) {
main {
width: 90vw;
margin: auto;
min-height: 85vh;
margin-top: 1em;
margin-bottom: 1em;
height: 100vh;
}
.expanding-panels {
grid-template-columns: repeat(2, 1fr);
.panel {
height: 40vh;
height: 50vh;
}
}
}
@ -168,16 +157,12 @@
grid-template-columns: repeat(4, 1fr);
.panel {
height: 75vh;
height: 80vh;
}
}
main {
width: 90vw;
margin: auto;
min-height: 85vh;
margin-top: 1em;
margin-bottom: 1em;
height: 80vh;
}
@ -186,6 +171,10 @@
/* Pantallas Ultrawide (1920px en adelante) */
@media (min-width: 1920px) {
main {
height: 80vh;
}
.expanding-panels {
grid-template-columns: repeat(4, 1fr);

View File

@ -6,7 +6,7 @@ main {
.parent {
padding: 5em;
/* padding: 5em; */
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
@ -16,24 +16,24 @@ main {
background-size: contain;
background-position: center;
background-repeat: no-repeat;
transition: all 0.1s cubic-bezier(0.25, 0.46, 0.45, 0.94);
border: 2px solid transparent;
/* border: 2px solid red; */
border-radius: 15px;
&:hover {
animation: vibrate 0.1s ease infinite !important;
transform: scale(1.05) !important;
box-shadow: 0 5px 15px rgba(255, 255, 255, 0.5) !important;
border-color: #00acc1 !important;
filter: brightness(1.05) !important;
z-index: 10 !important;
border-radius: 15px !important;
}
}
}
.parent div {
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
border: 2px solid transparent;
border-radius: 15px;
&:hover {
animation: vibrate 0.4s ease infinite !important;
transform: scale(1.05) !important;
box-shadow: 0 5px 15px rgba(255, 255, 255, 0.5) !important;
border-color: #00acc1 !important;
filter: brightness(1.05) !important;
z-index: 10 !important;
border-radius: 15px !important;
}
}
/* Imágenes específicas */
@ -61,20 +61,23 @@ main {
}
main {
place-items: center;
}
/* Smartphones (hasta 767px) */
@media (max-width: 767px) {
main {
width: 95vw;
min-height: 70vh;
margin: 10px auto;
min-height: 100vh;
background-size: auto 15%;
border-radius: 12px;
border-radius: 15px;
padding: 1em; /* Añadido para espacio interno */
}
.parent {
width: 100vw; /* Cambiado a 100% para mejor ajuste */
width: 100% !important;
padding: 1em; /* Reducido el padding para móviles */
display: grid;
@ -108,18 +111,15 @@ main {
/* Tablets (768px - 1023px) */
@media (min-width: 768px) and (max-width: 1023px) {
main {
width: 90vw;
min-height: 70vh;
margin: 10px auto;
background-size: auto 35%;
border-radius: 12px;
.parent {
width: 100% !important;
height: 50vw;
gap: 2em;
}
.parent {
width: 90vw;
/* Altura para que la grilla sea visible */
height: 80vh;
main {
background-size: 50% auto; /* 30% del ancho del contenedor */
height: 50vh;
}
}
@ -127,18 +127,15 @@ main {
/* Laptops (1024px - 1439px) */
@media (min-width: 1024px) and (max-width: 1439px) {
main {
width: 85vw;
min-height: 85vh;
margin: 10px auto;
background-size: auto 50%;
border-radius: 12px;
.parent {
width: 100% !important;
height: 65vw;
gap: 2em;
}
.parent {
width: 80vw;
/* Altura para que la grilla sea visible */
height: 80vh;
main {
background-size: 65% auto; /* 30% del ancho del contenedor */
height: 65vh;
}
}
@ -146,11 +143,15 @@ main {
/* PCs de escritorio (1440px - 1919px) */
@media (min-width: 1440px) and (max-width: 1919px) {
.parent {
width: 70vw;
/* Altura para que la grilla sea visible */
height: 70vh;
width: 100% !important;
height: 50vw;
gap: 2em;
}
main {
background-size: 45% auto; /* 30% del ancho del contenedor */
height: 80vh;
}
}
@ -158,14 +159,20 @@ main {
/* Pantallas Ultrawide (1920px en adelante) */
@media (min-width: 1920px) {
.parent {
width: 75vw;
width: 100% !important;
height: 40vw;
gap: 2em;
}
main {
background-size: 50% auto; /* 30% del ancho del contenedor */
min-height: 80vh;
}
}

View File

@ -3,3 +3,42 @@
font-size: 1.5rem;
}
}
main {
place-items: center;
}
/* Smartphones (hasta 767px) */
@media (max-width: 767px) {
/* main{ background-color: black; } */
}
/* Tablets (768px - 1023px) */
@media (min-width: 768px) and (max-width: 1023px) {
/* main{ background-color: pink; } */
}
/* Laptops (1024px - 1439px) monitores resulición baja */
@media (min-width: 1024px) and (max-width: 1439px) {
/* main{ background-color: purple; } */
main {
min-height: 85vh;
}
}
/* PCs de escritorio (1440px - 1919px) macbook */
@media (min-width: 1440px) and (max-width: 1919px) {
/* main{ background-color: greenyellow; } */
main {
min-height: 80vh;
}
}
/* Pantallas Ultrawide (1920px en adelante) */
@media (min-width: 1920px) {
/* main{ background-color: red; } */
main {
min-height: 80vh;
}
}

View File

@ -0,0 +1,61 @@
.form-header{
width: 100% !important;
& img {
width: 100px;
height: auto !important;
animation: rotacion 10s linear infinite;
transform-origin: center center; /* Asegura que gire desde el centro */
display: inline-block; /* Para mejor comportamiento en algunos navegadores */
}
}
@keyframes rotacion {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* Smartphones (hasta 767px) */
@media (max-width: 767px) {
/* main{ background-color: black; } */
main {
min-height: 80vh;
}
}
/* Tablets (768px - 1023px) */
@media (min-width: 768px) and (max-width: 1023px) {
/* main{ background-color: pink; } */
main {
min-height: 80vh;
}
}
/* Laptops (1024px - 1439px) monitores resulición baja */
@media (min-width: 1024px) and (max-width: 1439px) {
/* main{ background-color: purple; } */
main {
min-height: 80vh;
}
}
/* PCs de escritorio (1440px - 1919px) macbook */
@media (min-width: 1440px) and (max-width: 1919px) {
/* main{ background-color: greenyellow; } */
main {
min-height: 80vh;
}
}
/* Pantallas Ultrawide (1920px en adelante) */
@media (min-width: 1920px) {
/* main{ background-color: red; } */
main {
min-height: 80vh;
}
}

View File

@ -1,7 +1,9 @@
import {simpleNotification} from '../z_comps/notify.js';
for (let data of dataList) {
simpleNotification(data.title, data.body, data.typeAlert);
if (data != null){
simpleNotification(data.title, data.body, data.typeAlert);
}
}

44
static/g_login/login.css Normal file
View File

@ -0,0 +1,44 @@
main {
place-items: center;
}
/* Smartphones (hasta 767px) */
@media (max-width: 767px) {
/* main{ background-color: black; } */
main {
min-height: 80vh;
}
}
/* Tablets (768px - 1023px) */
@media (min-width: 768px) and (max-width: 1023px) {
/* main{ background-color: pink; } */
main {
min-height: 80vh;
}
}
/* Laptops (1024px - 1439px) monitores resulición baja */
@media (min-width: 1024px) and (max-width: 1439px) {
/* main{ background-color: purple; } */
main {
min-height: 80vh;
}
}
/* PCs de escritorio (1440px - 1919px) macbook */
@media (min-width: 1440px) and (max-width: 1919px) {
/* main{ background-color: greenyellow; } */
main {
min-height: 80vh;
}
}
/* Pantallas Ultrawide (1920px en adelante) */
@media (min-width: 1920px) {
/* main{ background-color: red; } */
main {
min-height: 80vh;
}
}

View File

@ -0,0 +1,251 @@
/* Contenedor general */
/* #dbContact_wrapper .row {
display: flex;
flex-wrap: wrap;
gap: 1em;
background: #f8f9fa;
padding: 1em;
border-radius: 8px;
} */
/* Sección de "entries per page" */
/* #dbContact_wrapper .dt-layout-start,
#dbContact_wrapper .dt-layout-end {
display: flex;
align-items: center;
gap: 0.5em;
} */
/* Ajuste a los selects */
/* #dbContact_wrapper .dt-length select,
#dbContact_wrapper .dt-search input[type="search"] {
min-width: 150px;
padding: 0.5em;
border-radius: 6px;
} */
/* Ajustes a los labels */
/* #dbContact_wrapper .dt-length label,
#dbContact_wrapper .dt-search label {
margin: 0;
font-size: 1em;
display: flex;
align-items: center;
gap: 0.5em;
} */
/* ------------------------ */
.dt-length label,
.dt-search label {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.dt-length::before {
content: "📄";
font-size: 0.9rem;
}
.dt-search::before {
content: "🔍";
font-size: 0.9rem;
margin-right: 0.5rem;
}
/* Smartphones (hasta 767px) */
@media (max-width: 767px) {
/* [ inicio info datatables ] */
#dbContact_wrapper> :first-child {
& div>div {
width: 100%;
display: grid;
grid-template-columns: 20% 80%;
place-items: center;
& select,
input {
width: 100% !important;
}
}
}
/* [ final info datatables ] */
/* [ i thead] */
thead > tr, th {
background-color: #333 !important;
}
th.status {
display: none;
}
thead th .filter {
visibility: visible;
position: absolute;
top: 50%;
left: 0;
right: 0;
transform: translateY(-50%);
}
thead th .filter input {
width: 100%;
padding: 0.5em;
font-size: 0.9em;
}
/* [ f thead] */
/* [ i select ] */
select.form-select {
width: 100% !important;
margin-top: 0.5em;
font-size: 0.9em;
padding: 0.5em;
}
/* [ f select ] */
/* [ i general table ] */
/* Eliminar estilos por defecto */
table, thead, tbody, th, td, tr {
all: unset;
}
/* Estilo para cada fila */
tr {
margin-top: 0.5em;
margin-bottom: 0.5em;
display: flex;
flex-direction: column;
background: #fff;
border: 2px solid #ccc;
border-radius: 10px;
padding: 0.5em;
/* gap: 0.8em; */
}
td.td-texto {
white-space: nowrap;
overflow: hidden;
text-align: left;
text-overflow: ellipsis;
max-width: 100%; /* Se adapta al contenedor */
display: inline-block;
vertical-align: middle; /* Alinea verticalmente */
}
/* Estilo para celdas */
td {
display: flex;
align-items: center;
padding: 0.6em 0;
/* border-bottom: 1px solid #eee; */
font-size: 0.9em;
flex-wrap: wrap;
}
/* Etiquetas de las celdas */
td::before, th::before {
content: attr(data-label);
font-weight: bold;
color: #333;
text-align: left;
flex-basis: 45%;
flex-shrink: 0;
}
}
#dbContact thead {
text-align: center;
vertical-align: middle;
background-color: black;
color: white;
}
#dbContact th {
text-align: center;
vertical-align: middle;
background-color: black;
color: white;
}
/* Tablets (768px - 1023px) */
@media (min-width: 768px) and (max-width: 1023px) {
/* main{ background-color: pink; } */
main {
min-height: 80vh;
/* background-color: blueviolet; */
}
}
/* Laptops (1024px - 1439px) monitores resulición baja */
@media (min-width: 1024px) and (max-width: 1439px) {
/* main{ background-color: purple; } */
main {
min-height: 50vh;
/* background-color: aqua; */
}
}
/* PCs de escritorio (1440px - 1919px) macbook */
@media (min-width: 1440px) and (max-width: 1919px) {
/* main{ background-color: greenyellow; } */
main {
min-height: 50vh;
}
}
/* Pantallas Ultrawide (1920px en adelante) */
@media (min-width: 1920px) {
/* main{ background-color: red; } */
main {
min-height: 80vh;
}
#dbContact thead {
position: sticky;
top: 0;
z-index: 10;
}
}
/* #dbContact th:nth-child(2),
#dbContact td:nth-child(2) {
display: none;
} */

View File

@ -0,0 +1,28 @@
new DataTable('#dbContact', {
autoWidth: true, // 👈 agregar esto
responsive: true,
initComplete: function () {
// Agrega campos de filtro para cada columna
this.api().columns().every(function () {
let column = this;
let header = $(column.header());
let title = header.text().trim();
// Excluir la columna "Estatus" del filtro
if (title !== 'Estatus') {
// Crea input de filtro
header.append('<div class="filter"><input type="text" class="form-control" placeholder=" Filtro ' + title + '" /></div>');
// Aplica el filtro al escribir
$('input', header)
.on('keyup change', function () {
if (column.search() !== this.value) {
column.search(this.value).draw();
}
});
}
});
}
});

View File

@ -0,0 +1,57 @@
// obtener los demás datos de la base de datos de contactos para mostrarlas en la ui
async function get_contact_data(btn) {
try {
let id = btn.dataset.id;
let modalBody = document.querySelector("#modalBody");
let response = await fetch('/user/get-contact-data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id }),
credentials: 'include'
});
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
let { data } = await response.json();
let contact = {
fecha: data[0],
fecha_hora: data[1],
nombre: data[2],
apellido: data[3],
correo: data[4],
estado: data[5],
telefono: data[6],
tamano_empresa: data[7],
rol_contacto: data[8],
tipo_industria: data[9],
comentarios: data[10],
estatus: data[11] ?? "Sin Estatus"
};
modalBody.innerHTML = `
<p><b><i class="bi bi-calendar4-week"></i></b> ${contact.fecha} - ${contact.fecha_hora}</p>
<p><b><i class="bi bi-person-fill"></i></b> ${contact.nombre} ${contact.apellido}</p>
<p><b><i class="bi bi-envelope-at-fill"></i></b> ${contact.correo}</p>
<p><b><i class="bi bi-pin-map-fill"></i></b> ${contact.estado}</p>
<p><b><i class="bi bi-telephone-fill"></i></b> ${contact.telefono}</p>
<p><b><i class="bi bi-people-fill"></i></b> ${contact.tamano_empresa}</p>
<p><b><i class="bi bi-person-vcard"></i></b> ${contact.rol_contacto}</p>
<p><b><i class="bi bi-shop"></i></b> ${contact.tipo_industria}</p>
<p><b><i class="bi bi-wrench-adjustable"></i></b> ${contact.estatus}</p>
<p><b><i class="bi bi-file-earmark-font-fill"></i></b> ${contact.comentarios}</p>
`;
} catch (error) {
console.error('Error al obtener datos:', error);
}
}
document.getElementById('dbContact').addEventListener('click', (event) => {
const button = event.target.closest('button.btn-primary[data-id]');
if (button) {
get_contact_data(button);
}
});

View File

@ -0,0 +1,29 @@
// actualiza los status en la base de datos
function send_data(target) {
let id = target.dataset.id;
let valor = target.value != "Null" ? target.value : null;
let data = { id, value: valor };
if (valor === 'Archivado') {
let table = $('#dbContact').DataTable();
let row = table.row(`tr[data-id="${id}"]`);
row.remove().draw();
}
fetch('/user/manage-record', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
credentials: 'include'
});
}
document.getElementById('dbContact').addEventListener('change', (event) => {
if (event.target.matches('select.form-select[data-id]')) {
send_data(event.target);
}
});

View File

@ -1,11 +1,11 @@
:root {
--blue-formha: #5d9dd1;
--navbar-footer-color: #5d9dd1;
--font-size-formha: 1.2rem;
}
.navbar-custom {
background-color: var(--blue-formha) !important;
background-color: var(--navbar-footer-color) !important;
font-size: var(--font-size-formha);
padding-top: 15px;
padding-bottom: 15px;
@ -64,24 +64,37 @@
margin-right: 1em;
}
/* logo bordeado blanco */
& .logo{
background-color: white;
border-radius: 10px;
background-image: url('../y_img/logos/formha_blanco_vertical.png');
width: 150px;
height: 100px;
background-size: cover; /* o cover según lo que busques */
background-repeat: no-repeat;
background-position: center;
}
}
.logo {
background-color: white;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
/* Animación de rotar el svg */
& .logo svg {
animation: rotar 5s linear infinite;
}
/* Definición de la animación */
@keyframes rotar {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
/* Estilos personalizados para el footer */
.footer {
background-color: var(--blue-formha);
background-color: var(--navbar-footer-color);
font-size: var(--font-size-formha);
color: white;
padding: 3rem 0;
@ -118,4 +131,52 @@
/* Smartphones (hasta 767px) */
@media (max-width: 767px) {
/* body{ background-color: black; } */
.logo {
padding: 2px;
width: 2.5em;
height: 2.5em;
}
}
/* Tablets (768px - 1023px) */
@media (min-width: 768px) and (max-width: 1023px) {
/* body{ background-color: pink; } */
.logo {
padding: 4px;
width: 2.5em;
height: 2.5em;
}
}
/* Laptops (1024px - 1439px) */
@media (min-width: 1024px) and (max-width: 1439px) {
/* body{ background-color: purple; } */
.logo {
padding: 6px;
width: 3em;
height: 3em;
}
}
/* PCs de escritorio (1440px - 1919px) */
@media (min-width: 1440px) and (max-width: 1919px) {
/* body{ background-color: greenyellow; } */
.logo {
padding: 4px;
width: 3em;
height: 3em;
}
}
/* Pantallas Ultrawide (1920px en adelante) */
@media (min-width: 1920px) {
/* body{ background-color: red; } */
.logo {
padding: 6px;
width: 3.5em;
height: 3.5em;
}
}

View File

@ -1,24 +1,50 @@
body {
font-family: "Source Sans 3", sans-serif !important;
font-family: "Roboto", sans-serif !important;
}
main{
display: grid;
margin: auto;
margin-top: 2em;
margin-bottom: 2em;
}
/* Smartphones (hasta 767px) */
@media (max-width: 767px) {
/* body{ background-color: black; } */
main {
width: 98vw !important;
}
}
/* Tablets (768px - 1023px) */
@media (min-width: 768px) and (max-width: 1023px) {
/* body{ background-color: pink; } */
main {
width: 96vw !important;
}
}
/* Laptops (1024px - 1439px) baja resolución */
@media (min-width: 1024px) and (max-width: 1439px) {
/* body{ background-color: purple; } */
main {
width: 95vw !important;
}
}
/* PCs de escritorio (1440px - 1919px) macbook */
@media (min-width: 1440px) and (max-width: 1919px) {
main{
width: 90vw !important;
}
}
/* Pantallas Ultrawide (1920px en adelante) */
@media (min-width: 1920px) {
main {
/* border: 6px solid red; */
/* max-width: 80vw !important; */
width: 80vw !important;
min-height: 85vh !important;
margin: auto;
margin-top: 2em;
margin-bottom: 2em;
display: grid;
/* place-content: center; */
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 352 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 KiB

After

Width:  |  Height:  |  Size: 419 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 418 KiB

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 KiB

After

Width:  |  Height:  |  Size: 255 KiB

View File

@ -21,25 +21,20 @@
</div> -->
<div class="parent">
<div class="i-i" data-toggle="modal" data-target="#forma-reclutamiento"
data-aos="zoom-in" data-aos-delay="0" data-aos-duration="800"></div>
<div class="i-i" data-toggle="modal" data-target="#forma-reclutamiento" data-aos="zoom-in" data-aos-delay="0" data-aos-duration="800"></div>
<div class="i-ii" data-toggle="modal" data-target="#forma-liderazgo"
data-aos="zoom-in" data-aos-delay="200" data-aos-duration="800"></div>
<div class="i-ii" data-toggle="modal" data-target="#forma-liderazgo"data-aos="zoom-in" data-aos-delay="200" data-aos-duration="800"></div>
<div class="i-iii" data-toggle="modal" data-target="#forma-capacitacion"
data-aos="zoom-in" data-aos-delay="300" data-aos-duration="800"></div>
<div class="i-iii" data-toggle="modal" data-target="#forma-capacitacion" data-aos="zoom-in" data-aos-delay="300" data-aos-duration="800"></div>
<div class="ii-i" data-toggle="modal" data-target="#forma-cambio"
data-aos="zoom-in" data-aos-delay="400" data-aos-duration="800"></div>
<div class="ii-i" data-toggle="modal" data-target="#forma-cambio" data-aos="zoom-in" data-aos-delay="400" data-aos-duration="800"></div>
<div class="ii-ii" data-toggle="modal" data-target="#forma-objetivos"
data-aos="zoom-in" data-aos-delay="500" data-aos-duration="800"></div>
<div class="ii-ii" data-toggle="modal" data-target="#forma-objetivos" data-aos="zoom-in" data-aos-delay="500" data-aos-duration="800"></div>
</div>
<!-- da forma reclutamiento -->
<div class="modal fade" id="forma-reclutamiento" tabindex="-1" role="dialog" aria-labelledby="forma-reclutamientoTitle" aria-hidden="true">
<div class="modal fade" id="forma-reclutamiento" tabindex="-1" role="dialog" aria-labelledby="forma-reclutamientoTitle" aria-hidden="true" >
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
<div class="modal-content" style="border: 6px solid #90b83b;">
<div class="modal-header">

View File

@ -10,8 +10,6 @@
{% block body %}
<div class="container py-5">
<h2 class="text-center mb-4">Nuestra Metodología</h2>
<p class="text-center text-muted mb-5">Implementamos soluciones con enfoque humano, técnico y estratégico.</p>

View File

@ -2,6 +2,7 @@
{% block css %}
<link rel="stylesheet" href="{{ url_for('static', filename='f_contact/form.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='f_contact/contact.css') }}">
{% endblock css %}
{% block navbar %}
@ -11,32 +12,6 @@
{% block body %}
<style>
.form-header{
width: 100% !important;
& img {
width: 100px;
height: auto !important;
animation: rotacion 10s linear infinite;
transform-origin: center center; /* Asegura que gire desde el centro */
display: inline-block; /* Para mejor comportamiento en algunos navegadores */
}
}
@keyframes rotacion {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
<div class="form-container" data-aos="zoom-out-down" data-aos-delay="0" data-aos-duration="800" data-aos-easing="ease-in-out">

View File

@ -2,6 +2,7 @@
{% block css %}
<link rel="stylesheet" href="{{ url_for('static', filename='f_contact/form.css') }}">
<link rel="stylesheet" href="{{ url_for( 'static', filename='g_login/login.css' ) }}">
{% endblock css %}
{% block navbar %}

View File

@ -2,6 +2,7 @@
{% block css %}
<link rel="stylesheet" href="{{ url_for('static', filename='f_contact/form.css') }}">
<link rel="stylesheet" href="{{ url_for( 'static', filename='g_login/login.css' ) }}">
{% endblock css %}
{% block navbar %}

View File

@ -2,6 +2,8 @@
{% block css %}
<link rel="stylesheet" href="{{ url_for('static', filename='h_tmp_user/a_home/a_home.css') }}">
<!-- {# Librería de aos.js [animaciones] #} -->
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
@ -18,58 +20,67 @@
{% block body %}
<div>
<h1>Solicitudes de Contacto</h1>
{% if is_admin %}
{% include 'z_comps/download_xlsx.html' %}
{% endif %}
<table id="dbContact" class="table table-striped" style="width:100%" data-aos="fade-right" data-aos-delay="0"
data-aos-duration="800" data-aos-easing="ease-in-out">
<thead>
<tr>
<th>Fecha</th>
<th>Nombre Completo</th>
<th>Estado</th>
<th>Tamaño Empresa</th>
<th>Rol Contacto</th>
<th>Tipo Industria</th>
<th>Estatus</th>
</tr>
</thead>
<tbody>
{% for item in data_contact %}
<tr data-id="{{item[0]}}">
<td>
<button data-id="{{item[0]}}" type="button" class="btn btn-primary" data-bs-toggle="modal"
data-bs-target="#modalContactData">
{{item[1]}}
</button>
</td>
<td>
{{item[2]}} {{item[3]}}
</td>
<td>{{item[4]}}</td>
<td>{{item[5]}}</td>
<td>{{item[6]}}</td>
<td>{{item[7]}}</td>
<td>
<select class="form-select" data-id="{{ item[0] }}">
<option value="Null" {% if item[8] is none %}selected{% endif %}></option>
<option value="Opción 1" {% if item[8]=='Opción 1' %}selected{% endif %}>Opción 1</option>
<option value="Opción 2" {% if item[8]=='Opción 2' %}selected{% endif %}>Opción 2</option>
<option value="Opción 3" {% if item[8]=='Opción 3' %}selected{% endif %}>Opción 3</option>
<option value="Opción 4" {% if item[8]=='Opción 4' %}selected{% endif %}>Opción 4</option>
<option value="Opción 5" {% if item[8]=='Opción 5' %}selected{% endif %}>Opción 5</option>
<option value="Opción 6" {% if item[8]=='Opción 6' %}selected{% endif %}>Opción 6</option>
<option value="Opción 7" {% if item[8]=='Opción 7' %}selected{% endif %}>Opción 7</option>
<option value="Archivado">Archivar</option>
</select>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div >
<div>
{% if is_admin %}
{% include 'z_comps/download_xlsx.html' %}
{% endif %}
</div>
<div data-aos="fade-right" data-aos-delay="0" data-aos-duration="800" data-aos-easing="ease-in-out" >
<table id="dbContact" class="table table-striped" >
<caption>Solicitudes de Contacto</caption>
<thead>
<tr>
<th data-header="Fecha">Fecha</th>
<th data-header="Nombre">Nombre</th>
<th data-header="Estado">Estado</th>
<th data-header="Empleados">Empleados</th>
<th data-header="Rol">Rol</th>
<th data-header="Industria">Industria</th>
<th data-header="Estatus" class="status">Estatus</th>
</tr>
</thead>
<tbody>
{% for item in data_contact %}
<tr data-id="{{item[0]}}">
<td data-label="Fecha: " class="td-texto">
<button data-id="{{item[0]}}" type="button" class="btn btn-primary" data-bs-toggle="modal"
data-bs-target="#modalContactData">
{{item[1]}}
</button>
</td>
<td data-label="Nombre:" class="td-texto">
{{item[2]}} {{item[3]}}
</td>
<td data-label="Estado: " class="td-texto">{{item[4]}}</td>
<td data-label="Empleados: " class="td-texto">{{item[5]}}</td>
<td data-label="Rol: " class="td-texto">{{item[6]}}</td>
<td data-label="Industria: " class="td-texto">{{item[7]}}</td>
<td data-label="Estatus:">
<select class="form-select" data-id="{{ item[0] }}">
<option value="Null" {% if item[8] is none %}selected{% endif %}></option>
<option value="Opción 1" {% if item[8]=='Opción 1' %}selected{% endif %}>Opción 1</option>
<option value="Opción 2" {% if item[8]=='Opción 2' %}selected{% endif %}>Opción 2</option>
<option value="Opción 3" {% if item[8]=='Opción 3' %}selected{% endif %}>Opción 3</option>
<option value="Opción 4" {% if item[8]=='Opción 4' %}selected{% endif %}>Opción 4</option>
<option value="Opción 5" {% if item[8]=='Opción 5' %}selected{% endif %}>Opción 5</option>
<option value="Opción 6" {% if item[8]=='Opción 6' %}selected{% endif %}>Opción 6</option>
<option value="Opción 7" {% if item[8]=='Opción 7' %}selected{% endif %}>Opción 7</option>
<option value="Archivado">Archivar</option>
</select>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Modal -->
@ -101,115 +112,12 @@
<!-- {# aos script #} -->
{% include 'z_comps/aos_script.html' %}
<script>
function getFechaHoraFormato() {
const now = new Date();
const pad = (n) => n.toString().padStart(2, '0');
const dia = pad(now.getDate());
const mes = pad(now.getMonth() + 1); // Enero es 0
const anio = now.getFullYear();
const hora = pad(now.getHours());
const minuto = pad(now.getMinutes());
return `${dia}.${mes}.${anio}_${hora}_${minuto}`;
}
</script>
<!-- {# obtener toda la información de la db del registro seleccionado #} -->
<script src="{{ url_for('static', filename='h_tmp_user/a_home/get_contact_data.js') }}"></script>
<script>
async function get_contact_data(btn) {
try {
let id = btn.dataset.id;
let modalBody = document.querySelector("#modalBody");
let response = await fetch('/user/get-contact-data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id }),
credentials: 'include'
});
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
let { data } = await response.json();
let contact = {
fecha: data[0],
fecha_hora: data[1],
nombre: data[2],
apellido: data[3],
correo: data[4],
estado: data[5],
telefono: data[6],
tamano_empresa: data[7],
rol_contacto: data[8],
tipo_industria: data[9],
comentarios: data[10],
estatus: data[11] ?? "Sin Estatus"
};
modalBody.innerHTML = `
<p><b><i class="bi bi-calendar4-week"></i></b> ${contact.fecha} - ${contact.fecha_hora}</p>
<p><b><i class="bi bi-person-fill"></i></b> ${contact.nombre} ${contact.apellido}</p>
<p><b><i class="bi bi-envelope-at-fill"></i></b> ${contact.correo}</p>
<p><b><i class="bi bi-pin-map-fill"></i></b> ${contact.estado}</p>
<p><b><i class="bi bi-telephone-fill"></i></b> ${contact.telefono}</p>
<p><b><i class="bi bi-people-fill"></i></b> ${contact.tamano_empresa}</p>
<p><b><i class="bi bi-person-vcard"></i></b> ${contact.rol_contacto}</p>
<p><b><i class="bi bi-shop"></i></b> ${contact.tipo_industria}</p>
<p><b><i class="bi bi-wrench-adjustable"></i></b> ${contact.estatus}</p>
<p><b><i class="bi bi-file-earmark-font-fill"></i></b> ${contact.comentarios}</p>
`;
} catch (error) {
console.error('Error al obtener datos:', error);
}
}
document.getElementById('dbContact').addEventListener('click', (event) => {
const button = event.target.closest('button.btn-primary[data-id]');
if (button) {
get_contact_data(button);
}
});
</script>
<script>
function send_data(target) {
let id = target.dataset.id;
let valor = target.value != "Null" ? target.value : null;
let data = { id, value: valor };
if (valor === 'Archivado') {
let table = $('#dbContact').DataTable();
let row = table.row(`tr[data-id="${id}"]`);
row.remove().draw();
}
fetch('/user/manage-record', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
credentials: 'include'
});
}
document.getElementById('dbContact').addEventListener('change', (event) => {
if (event.target.matches('select.form-select[data-id]')) {
send_data(event.target);
}
});
</script>
<script>
</script>
<!-- {# actualizar los datos del estatus del contacto #} -->
<script src="{{ url_for( 'static', filename='h_tmp_user/a_home/update_status_contacts.js' ) }}"></script>
<!-- js datatables -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.3.0/js/bootstrap.bundle.min.js"></script>
@ -224,58 +132,10 @@ document.getElementById('dbContact').addEventListener('click', (event) => {
<!-- DataTables Bootstrap 5 JS -->
<script src="https://cdn.datatables.net/2.2.2/js/dataTables.bootstrap5.js"></script>
<script src="{{ url_for( 'static', filename='h_tmp_user/a_home/datatable.js' ) }}"></script>
<script>
new DataTable('#dbContact', {
initComplete: function() {
// Agrega campos de filtro para cada columna
this.api().columns().every(function() {
let column = this;
let header = $(column.header());
let title = header.text().trim();
// Excluir la columna "Estatus" del filtro
if (title !== 'Estatus') {
// Crea input de filtro
header.append('<div class="filter"><input type="text" class="form-control" placeholder="'+title+'" /></div>');
// Aplica el filtro al escribir
$('input', header)
.on('keyup change', function() {
if (column.search() !== this.value) {
column.search(this.value).draw();
}
});
}
});
}
});
</script>
<!-- <script>
new DataTable('#dbContact', {
initComplete: function() {
// Agrega campos de filtro para cada columna
this.api().columns().every(function() {
let column = this;
let header = $(column.header());
let title = header.text().trim();
// Crea input de filtro
// <i class="bi bi-filter"></i>
header.append('<div class="filter"><input type="text" class="form-control" placeholder="'+title+'" /></div>');
// Aplica el filtro al escribir
$('input', header)
.on('keyup change', function() {
if (column.search() !== this.value) {
column.search(this.value).draw();
}
});
});
}
});
</script> -->
<!-- {# tiempo de expiración para el usuario #} -->
<script>
let exp = "{{exp}}";
</script>

View File

@ -9,6 +9,10 @@
{% block title %}{{ title | default('USER FORMHä') }}{% endblock %}
</title>
<!-- {# i google analytics #} -->
{% include 'z_comps/google_analytics.html' %}
<!-- {# f google analytics #} -->
<!-- {# Librería de aos.js [animaciones] #} -->
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
@ -45,7 +49,41 @@
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('user_home') }}">
<div class="logo"></div>
<!-- {# inicio logo #} -->
<div class="logo">
<?xml version="1.0" encoding="UTF-8"?>
<svg id="info" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 515.86 515.86">
<!-- Generator: Adobe Illustrator 29.4.0, SVG Export Plug-In . SVG Version: 2.1.0 Build 152) -->
<defs>
<style>
.st0 {
fill: #699dd3;
}
.st1 {
fill: #003374;
}
.st2 {
fill: #861e5d;
}
.st3 {
fill: #93b635;
}
</style>
</defs>
<path class="st1"
d="M257.93,0C115.48,0,0,115.48,0,257.93s115.48,257.93,257.93,257.93,257.93-115.48,257.93-257.93S400.38,0,257.93,0ZM257.93,374.4c-64.32,0-116.47-52.14-116.47-116.47s52.14-116.47,116.47-116.47,116.47,52.14,116.47,116.47-52.14,116.47-116.47,116.47Z" />
<path class="st0"
d="M257.93,17.99C125.41,17.99,17.99,125.41,17.99,257.93s107.43,239.94,239.94,239.94,239.94-107.43,239.94-239.94S390.45,17.99,257.93,17.99ZM257.93,374.4c-64.32,0-116.47-52.14-116.47-116.47s52.14-116.47,116.47-116.47,116.47,52.14,116.47,116.47-52.14,116.47-116.47,116.47Z" />
<path class="st2"
d="M152.7,307.88c-7.2-15.14-11.24-32.07-11.24-49.95s4.05-34.84,11.26-49.99c16.96-56.07,68.26-97.9,171.82-97.9,19.54,0,38.4,2.92,56.16,8.35,6.31,1.93,10.5-6.48,5.14-10.32-39.97-28.63-88.93-45.49-141.85-45.49C117.37,62.58,13.29,159.04,1.19,282.49c12.37,130.93,122.57,233.37,256.74,233.37,41.87,0,81.36-10.04,116.32-27.74-15.86,4.24-32.52,6.51-49.72,6.51-72.39,0-149.29-92.49-171.84-186.75Z" />
<path class="st3"
d="M497.87,300.26c0-18.96-3.56-37.08-9.99-53.78-.34-.88-.68-1.76-1.04-2.63-.5-1.26-1.05-2.5-1.58-3.74-1.68-3.88-3.45-7.72-5.43-11.43-.01.07-.02.13-.03.2-25.37-46.71-74.85-78.43-131.74-78.43-12.4,0-24.44,1.54-35.96,4.38,38.48,20.26,64.26,61.4,62.19,108.38-2.65,59.96-51.6,108.7-111.57,111.1-47.26,1.89-88.55-24.41-108.5-63.43-22.95-30.47-36.58-68.37-36.58-109.46,0-12.39,1.25-24.49,3.62-36.18,1.23-6.08-6.66-9.54-10.43-4.6-29.23,38.36-45.92,86.78-43.9,139.18,4.37,113.08,97.12,204.44,210.25,207.21,104.27,2.55,192.24-68.89,215.29-165.52.76-3.17,1.42-6.38,2.03-9.6,1.6-7.46,2.66-15.11,3.11-22.94.03-.33.07-.65.09-.98.1-2.31.18-4.62.18-6.96,0-.11-.01-.23-.01-.34,0-.14.01-.28.01-.42Z" />
</svg>
</div>
<!-- {# fin logo #} -->
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"

View File

@ -12,13 +12,17 @@
<meta name="description" content="Reclutamiento y selección, detección de necesidades de capacitación, capacitación, evaluación del desempeño, encuestas de clima y cultura, NOM 025 y NOM 035.">
<!-- {# i google analytics #} -->
{% include 'z_comps/google_analytics.html' %}
<!-- {# f google analytics #} -->
<!-- {# Librería de aos.js [animaciones] #} -->
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
<!-- {# i fontts #} -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Source+Sans+3:wght@400;500;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<!-- {# f fonts #} -->
<!-- {# i bootstrap #} -->

View File

@ -0,0 +1,9 @@
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-9WG74PZEE5"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag('js', new Date());
gtag('config', 'G-9WG74PZEE5');
</script>

View File

@ -3,12 +3,41 @@
<nav class="navbar navbar-expand-lg bg-body-tertiary navbar-custom">
<div class="container-fluid">
<a class="navbar-brand" href="{{ url_for('home') }}">
<!-- {# inicio logo #} -->
<div class="logo">
<?xml version="1.0" encoding="UTF-8"?>
<svg id="info" xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 515.86 515.86">
<!-- Generator: Adobe Illustrator 29.4.0, SVG Export Plug-In . SVG Version: 2.1.0 Build 152) -->
<defs>
<style>
.st0 {
fill: #699dd3;
}
.st1 {
fill: #003374;
}
<div class="logo"></div>
.st2 {
fill: #861e5d;
}
<!-- {# {% include 'comps/formha.html' %} #} -->
.st3 {
fill: #93b635;
}
</style>
</defs>
<path class="st1"
d="M257.93,0C115.48,0,0,115.48,0,257.93s115.48,257.93,257.93,257.93,257.93-115.48,257.93-257.93S400.38,0,257.93,0ZM257.93,374.4c-64.32,0-116.47-52.14-116.47-116.47s52.14-116.47,116.47-116.47,116.47,52.14,116.47,116.47-52.14,116.47-116.47,116.47Z" />
<path class="st0"
d="M257.93,17.99C125.41,17.99,17.99,125.41,17.99,257.93s107.43,239.94,239.94,239.94,239.94-107.43,239.94-239.94S390.45,17.99,257.93,17.99ZM257.93,374.4c-64.32,0-116.47-52.14-116.47-116.47s52.14-116.47,116.47-116.47,116.47,52.14,116.47,116.47-52.14,116.47-116.47,116.47Z" />
<path class="st2"
d="M152.7,307.88c-7.2-15.14-11.24-32.07-11.24-49.95s4.05-34.84,11.26-49.99c16.96-56.07,68.26-97.9,171.82-97.9,19.54,0,38.4,2.92,56.16,8.35,6.31,1.93,10.5-6.48,5.14-10.32-39.97-28.63-88.93-45.49-141.85-45.49C117.37,62.58,13.29,159.04,1.19,282.49c12.37,130.93,122.57,233.37,256.74,233.37,41.87,0,81.36-10.04,116.32-27.74-15.86,4.24-32.52,6.51-49.72,6.51-72.39,0-149.29-92.49-171.84-186.75Z" />
<path class="st3"
d="M497.87,300.26c0-18.96-3.56-37.08-9.99-53.78-.34-.88-.68-1.76-1.04-2.63-.5-1.26-1.05-2.5-1.58-3.74-1.68-3.88-3.45-7.72-5.43-11.43-.01.07-.02.13-.03.2-25.37-46.71-74.85-78.43-131.74-78.43-12.4,0-24.44,1.54-35.96,4.38,38.48,20.26,64.26,61.4,62.19,108.38-2.65,59.96-51.6,108.7-111.57,111.1-47.26,1.89-88.55-24.41-108.5-63.43-22.95-30.47-36.58-68.37-36.58-109.46,0-12.39,1.25-24.49,3.62-36.18,1.23-6.08-6.66-9.54-10.43-4.6-29.23,38.36-45.92,86.78-43.9,139.18,4.37,113.08,97.12,204.44,210.25,207.21,104.27,2.55,192.24-68.89,215.29-165.52.76-3.17,1.42-6.38,2.03-9.6,1.6-7.46,2.66-15.11,3.11-22.94.03-.33.07-.65.09-.98.1-2.31.18-4.62.18-6.96,0-.11-.01-.23-.01-.34,0-.14.01-.28.01-.42Z" />
</svg>
</div>
<!-- {# fin logo #} -->
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>