add landing page
This commit is contained in:
@@ -1,13 +1,176 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>frontend</title>
|
||||
<title>Control de Patentes - ALPR</title>
|
||||
<meta name="description" content="Sistema de Control de Acceso mediante Reconocimiento Automático de Patentes" />
|
||||
|
||||
<!-- Loading Screen Styles (inline para carga inmediata) -->
|
||||
<style>
|
||||
/* Loading screen container */
|
||||
#loading-screen {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #0f172a 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 9999;
|
||||
transition: opacity 0.5s ease-out;
|
||||
}
|
||||
|
||||
#loading-screen.fade-out {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Logo container with glow effect */
|
||||
.loading-logo {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
margin-bottom: 30px;
|
||||
animation: pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.loading-logo svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
filter: drop-shadow(0 0 20px rgba(59, 130, 246, 0.5));
|
||||
}
|
||||
|
||||
/* Spinner ring */
|
||||
.spinner-ring {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 3px solid rgba(59, 130, 246, 0.2);
|
||||
border-top-color: #3b82f6;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
/* Loading text */
|
||||
.loading-text {
|
||||
color: #94a3b8;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
font-size: 16px;
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.loading-subtext {
|
||||
color: #64748b;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Progress bar */
|
||||
.progress-container {
|
||||
width: 200px;
|
||||
height: 4px;
|
||||
background: rgba(59, 130, 246, 0.2);
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, #3b82f6, #8b5cf6, #3b82f6);
|
||||
background-size: 200% 100%;
|
||||
animation: shimmer 1.5s ease-in-out infinite;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { transform: scale(1); opacity: 1; }
|
||||
50% { transform: scale(1.05); opacity: 0.8; }
|
||||
}
|
||||
|
||||
@keyframes shimmer {
|
||||
0% { background-position: -200% 0; }
|
||||
100% { background-position: 200% 0; }
|
||||
}
|
||||
|
||||
/* Dots animation */
|
||||
.loading-dots::after {
|
||||
content: '';
|
||||
animation: dots 1.5s steps(4, end) infinite;
|
||||
}
|
||||
|
||||
@keyframes dots {
|
||||
0%, 20% { content: ''; }
|
||||
40% { content: '.'; }
|
||||
60% { content: '..'; }
|
||||
80%, 100% { content: '...'; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Loading Screen (se remueve cuando React carga) -->
|
||||
<div id="loading-screen">
|
||||
<!-- Logo SVG (Car + Shield icon) -->
|
||||
<div class="loading-logo">
|
||||
<svg viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Shield background -->
|
||||
<path d="M50 8L15 25V50C15 72 30 88 50 95C70 88 85 72 85 50V25L50 8Z"
|
||||
fill="url(#shield-gradient)" stroke="#3b82f6" stroke-width="2"/>
|
||||
<!-- Car silhouette -->
|
||||
<path d="M30 55H70M35 45H65L60 38H40L35 45ZM32 55V62H38V55H32ZM62 55V62H68V55H62Z"
|
||||
stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<!-- Plate icon -->
|
||||
<rect x="38" y="48" width="24" height="8" rx="1" fill="#3b82f6" stroke="#fff" stroke-width="1"/>
|
||||
<text x="50" y="54" text-anchor="middle" fill="#fff" font-size="5" font-family="monospace" font-weight="bold">ALPR</text>
|
||||
<!-- Gradient definitions -->
|
||||
<defs>
|
||||
<linearGradient id="shield-gradient" x1="15" y1="8" x2="85" y2="95" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0%" stop-color="#1e40af"/>
|
||||
<stop offset="100%" stop-color="#3730a3"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- Spinner -->
|
||||
<div class="spinner-ring"></div>
|
||||
|
||||
<!-- Loading text -->
|
||||
<div class="loading-text">Control de Patentes</div>
|
||||
<div class="loading-subtext">Cargando sistema<span class="loading-dots"></span></div>
|
||||
|
||||
<!-- Progress bar -->
|
||||
<div class="progress-container">
|
||||
<div class="progress-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
|
||||
<!-- Script para remover loading screen cuando React está listo -->
|
||||
<script>
|
||||
// Fallback: remover loading screen después de 10 segundos máximo
|
||||
setTimeout(function() {
|
||||
var loadingScreen = document.getElementById('loading-screen');
|
||||
if (loadingScreen) {
|
||||
loadingScreen.classList.add('fade-out');
|
||||
setTimeout(function() {
|
||||
loadingScreen.remove();
|
||||
}, 500);
|
||||
}
|
||||
}, 10000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,10 +1,27 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import './index.css'
|
||||
import './i18n'
|
||||
import App from './App.jsx'
|
||||
|
||||
// Función para remover la pantalla de carga
|
||||
const removeLoadingScreen = () => {
|
||||
const loadingScreen = document.getElementById('loading-screen');
|
||||
if (loadingScreen) {
|
||||
loadingScreen.classList.add('fade-out');
|
||||
setTimeout(() => {
|
||||
loadingScreen.remove();
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
// Renderizar React y remover loading screen
|
||||
createRoot(document.getElementById('root')).render(
|
||||
<StrictMode>
|
||||
<App />
|
||||
</StrictMode>,
|
||||
)
|
||||
|
||||
// Remover loading screen cuando React esté montado
|
||||
// Pequeño delay para asegurar que la UI esté lista
|
||||
setTimeout(removeLoadingScreen, 100);
|
||||
|
||||
Reference in New Issue
Block a user