Initial commit: Vite + React project setup
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
162
README.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# Maya Contigo - Banorte Interface
|
||||
|
||||
Aplicación web moderna desarrollada con **Vite + React + TailwindCSS** que replica el diseño de la interfaz "Maya Contigo" de Banorte.
|
||||
|
||||
## Características
|
||||
|
||||
- **Header fijo** con branding de Banorte
|
||||
- **Hero Banner** con efectos de iluminación circular roja
|
||||
- **Carrusel configurable** con navegación suave y animaciones
|
||||
- **Diseño responsivo** para móvil, tablet y desktop
|
||||
- **Sin librerías externas** para el carrusel (implementación custom)
|
||||
- **Fácil de extender** - solo edita el archivo de datos
|
||||
|
||||
## Tecnologías
|
||||
|
||||
- ⚡ **Vite** - Build tool rápido
|
||||
- ⚛️ **React 18** - UI Library
|
||||
- 🎨 **TailwindCSS** - Utility-first CSS framework
|
||||
- 🎯 **CSS Custom** - Animaciones y transiciones suaves
|
||||
|
||||
## Instalación
|
||||
|
||||
1. **Clonar e instalar dependencias:**
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. **Iniciar servidor de desarrollo:**
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
3. **Abrir en el navegador:**
|
||||
|
||||
El servidor se iniciará en `http://localhost:5173`
|
||||
|
||||
## Estructura del Proyecto
|
||||
|
||||
```
|
||||
myinterfaz/
|
||||
├── public/
|
||||
│ └── images/ # Imágenes de los módulos
|
||||
│ ├── rh.png
|
||||
│ ├── normativa.png
|
||||
│ ├── cx.png
|
||||
│ ├── bursatil.png
|
||||
│ └── pyme.png
|
||||
├── src/
|
||||
│ ├── components/
|
||||
│ │ ├── Header.jsx # Header fijo con logo
|
||||
│ │ ├── Hero.jsx # Banner principal
|
||||
│ │ └── Carousel.jsx # Carrusel configurable
|
||||
│ ├── data/
|
||||
│ │ └── modules.js # Datos de los módulos
|
||||
│ ├── App.jsx # Componente principal
|
||||
│ ├── main.jsx # Entry point
|
||||
│ └── index.css # Estilos globales
|
||||
├── index.html
|
||||
├── vite.config.js
|
||||
├── tailwind.config.js
|
||||
└── package.json
|
||||
```
|
||||
|
||||
## Cómo Agregar Nuevos Módulos
|
||||
|
||||
Es muy fácil agregar nuevos módulos al carrusel. Solo necesitas editar el archivo `src/data/modules.js`:
|
||||
|
||||
```javascript
|
||||
export const modules = [
|
||||
// Módulos existentes...
|
||||
{
|
||||
id: 6, // ID único
|
||||
title: "MAYA CONTIGO", // Título superior (azul)
|
||||
subtitle: "NUEVO MODULO", // Subtítulo (rojo)
|
||||
img: "/images/nuevo-modulo.png", // Ruta de la imagen
|
||||
url: "https://example.com/nuevo" // URL de destino
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
### Pasos para agregar un módulo:
|
||||
|
||||
1. **Agregar la imagen** en `public/images/`
|
||||
2. **Editar** `src/data/modules.js`
|
||||
3. **Agregar un nuevo objeto** al array con los campos requeridos
|
||||
4. ¡Listo! El carrusel se actualizará automáticamente
|
||||
|
||||
## Colores de Marca Banorte
|
||||
|
||||
Los colores están configurados en `tailwind.config.js`:
|
||||
|
||||
- **Rojo Banorte:** `#C8102E` (usa `bg-banorte-red` o `text-banorte-red`)
|
||||
- **Azul Banorte:** `#001A4D` (usa `bg-banorte-blue` o `text-banorte-blue`)
|
||||
|
||||
## Personalización
|
||||
|
||||
### Cambiar el tamaño del carrusel
|
||||
|
||||
Edita las clases de tamaño en `src/components/Carousel.jsx`:
|
||||
|
||||
```jsx
|
||||
// Busca estas clases en el estilo inline
|
||||
.active-item .circle-container {
|
||||
width: 240px; // Tamaño del círculo activo
|
||||
height: 240px;
|
||||
}
|
||||
```
|
||||
|
||||
### Modificar velocidad de animación
|
||||
|
||||
Cambia la duración de la transición:
|
||||
|
||||
```jsx
|
||||
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
// Cambia 0.5s por el valor deseado
|
||||
```
|
||||
|
||||
## Comandos Disponibles
|
||||
|
||||
```bash
|
||||
# Desarrollo
|
||||
npm run dev
|
||||
|
||||
# Build para producción
|
||||
npm run build
|
||||
|
||||
# Preview del build
|
||||
npm run preview
|
||||
```
|
||||
|
||||
## Características del Carrusel
|
||||
|
||||
- ✅ **Navegación con flechas** izquierda/derecha
|
||||
- ✅ **Elemento central ampliado** con efecto de enfoque
|
||||
- ✅ **Animaciones suaves** entre transiciones
|
||||
- ✅ **Responsive** - se adapta a diferentes pantallas
|
||||
- ✅ **Click para navegar** - click en el elemento activo abre el URL
|
||||
- ✅ **Escala y opacidad** para elementos no activos
|
||||
- ✅ **Sin librerías externas** - implementación 100% custom
|
||||
|
||||
## Responsive
|
||||
|
||||
- **Móvil (< 768px):** Muestra 3 elementos (1 central + 2 laterales)
|
||||
- **Tablet (768-1024px):** Muestra 3-5 elementos
|
||||
- **Desktop (> 1024px):** Muestra 5 elementos completos
|
||||
|
||||
## Soporte de Navegadores
|
||||
|
||||
- Chrome (últimas 2 versiones)
|
||||
- Firefox (últimas 2 versiones)
|
||||
- Safari (últimas 2 versiones)
|
||||
- Edge (últimas 2 versiones)
|
||||
|
||||
## Licencia
|
||||
|
||||
Proyecto educativo - Banorte Maya Contigo Interface
|
||||
|
||||
---
|
||||
|
||||
**Desarrollado con ❤️ usando Vite + React + TailwindCSS**
|
||||
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!doctype html>
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="public/images/brujula.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Maya Contigo - Banorte</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
2577
package-lock.json
generated
Normal file
22
package.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "maya-contigo-interface",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"postcss": "^8.4.49",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"vite": "^5.4.11"
|
||||
}
|
||||
}
|
||||
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export default {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
BIN
public/images/banortelogo.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/images/brujula.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/images/brujula_elipse.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
11
public/images/bursatil.png
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="grad4" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#C8102E;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#001A4D;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="400" height="400" fill="url(#grad4)"/>
|
||||
<text x="200" y="180" font-family="Arial, sans-serif" font-size="55" font-weight="bold" fill="white" text-anchor="middle">BURSA</text>
|
||||
<text x="200" y="250" font-family="Arial, sans-serif" font-size="55" font-weight="bold" fill="white" text-anchor="middle">TIL</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 648 B |
BIN
public/images/chat_maya_default_avatar.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
10
public/images/cx.png
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="grad3" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#001A4D;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#C8102E;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="400" height="400" fill="url(#grad3)"/>
|
||||
<text x="200" y="220" font-family="Arial, sans-serif" font-size="100" font-weight="bold" fill="white" text-anchor="middle">CX</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 511 B |
BIN
public/images/flecha-der.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
public/images/flecha-izq.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
public/images/grcas.png
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
public/images/hero_0.png
Normal file
|
After Width: | Height: | Size: 457 KiB |
BIN
public/images/image.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
public/images/normativa.png
Normal file
|
After Width: | Height: | Size: 196 KiB |
BIN
public/images/pruebas.png
Normal file
|
After Width: | Height: | Size: 211 KiB |
10
public/images/pyme.png
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="grad5" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#001A4D;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#C8102E;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="400" height="400" fill="url(#grad5)"/>
|
||||
<text x="200" y="220" font-family="Arial, sans-serif" font-size="80" font-weight="bold" fill="white" text-anchor="middle">PYME</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 512 B |
BIN
public/images/rh.png
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
public/images/riesgos.png
Normal file
|
After Width: | Height: | Size: 186 KiB |
28
src/App.jsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import Header from './components/Header';
|
||||
import Hero from './components/Hero';
|
||||
import Carousel from './components/Carousel';
|
||||
import { modules } from './data/modules';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div
|
||||
className="min-h-screen bg-gray-50"
|
||||
style={{
|
||||
backgroundImage: 'url(/images/grcas.png)',
|
||||
backgroundRepeat: 'repeat',
|
||||
backgroundSize: 'auto',
|
||||
backgroundAttachment: 'fixed'
|
||||
}}
|
||||
>
|
||||
<Header />
|
||||
<main>
|
||||
<Hero />
|
||||
<Carousel items={modules} />
|
||||
</main>
|
||||
<footer className="w-full h-8 bg-banorte-red mt-auto"></footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
194
src/components/Carousel.css
Normal file
@@ -0,0 +1,194 @@
|
||||
.carousel-item {
|
||||
position: absolute;
|
||||
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.circle-container {
|
||||
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.circle-inner {
|
||||
border-radius: 50%;
|
||||
background: white;
|
||||
padding: 4px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.circle-inner::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
transition: opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Active (Center) Item */
|
||||
.active-item {
|
||||
transform: translateX(0) scale(1);
|
||||
z-index: 20;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.active-item .circle-container {
|
||||
width: 240px;
|
||||
height: 240px;
|
||||
}
|
||||
|
||||
.active-item .circle-inner {
|
||||
box-shadow: 0 20px 40px rgba(200, 16, 46, 0.4);
|
||||
}
|
||||
|
||||
.active-item .circle-inner::before {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.active-item .item-title {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
.active-item .item-subtitle {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
/* Left Item */
|
||||
.left-item {
|
||||
transform: translateX(-380px) scale(0.75);
|
||||
z-index: 10;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.left-item .circle-container {
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
.left-item .item-title {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.left-item .item-subtitle {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
/* Right Item */
|
||||
.right-item {
|
||||
transform: translateX(380px) scale(0.75);
|
||||
z-index: 10;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.right-item .circle-container {
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
.right-item .item-title {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.right-item .item-subtitle {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
/* Far Left Item */
|
||||
.far-left-item {
|
||||
transform: translateX(-650px) scale(0.6);
|
||||
z-index: 5;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.far-left-item .circle-container {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.far-left-item .item-title {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.far-left-item .item-subtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* Far Right Item */
|
||||
.far-right-item {
|
||||
transform: translateX(650px) scale(0.6);
|
||||
z-index: 5;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.far-right-item .circle-container {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.far-right-item .item-title {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.far-right-item .item-subtitle {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* Hidden Items */
|
||||
.hidden-item {
|
||||
transform: translateX(0) scale(0.3);
|
||||
z-index: 0;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.hidden-item .circle-container {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
/* Hover Effects */
|
||||
.active-item:hover .circle-inner {
|
||||
box-shadow: 0 24px 48px rgba(200, 16, 46, 0.5);
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 768px) {
|
||||
.active-item .circle-container {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.left-item,
|
||||
.right-item {
|
||||
transform: translateX(0) scale(0.5);
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.left-item {
|
||||
transform: translateX(-160px) scale(0.5);
|
||||
}
|
||||
|
||||
.right-item {
|
||||
transform: translateX(160px) scale(0.5);
|
||||
}
|
||||
|
||||
.left-item .circle-container,
|
||||
.right-item .circle-container {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
}
|
||||
|
||||
.far-left-item,
|
||||
.far-right-item,
|
||||
.hidden-item {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
131
src/components/Carousel.jsx
Normal file
@@ -0,0 +1,131 @@
|
||||
import React, { useState } from 'react';
|
||||
import './Carousel.css';
|
||||
|
||||
const Carousel = ({ items }) => {
|
||||
const [activeIndex, setActiveIndex] = useState(2); // Start with middle item
|
||||
|
||||
const handleNext = () => {
|
||||
setActiveIndex((prev) => (prev + 1) % items.length);
|
||||
};
|
||||
|
||||
const handlePrev = () => {
|
||||
setActiveIndex((prev) => (prev - 1 + items.length) % items.length);
|
||||
};
|
||||
|
||||
const handleItemClick = (url) => {
|
||||
window.location.href = url;
|
||||
};
|
||||
|
||||
// Function to get the position class for each item
|
||||
const getPositionClass = (index) => {
|
||||
const diff = index - activeIndex;
|
||||
const length = items.length;
|
||||
|
||||
// Normalize difference to handle circular array
|
||||
let normalizedDiff = diff;
|
||||
if (Math.abs(diff) > length / 2) {
|
||||
normalizedDiff = diff > 0 ? diff - length : diff + length;
|
||||
}
|
||||
|
||||
if (normalizedDiff === 0) {
|
||||
return 'active-item'; // Center
|
||||
} else if (normalizedDiff === -1) {
|
||||
return 'left-item'; // Immediate left
|
||||
} else if (normalizedDiff === 1) {
|
||||
return 'right-item'; // Immediate right
|
||||
} else if (normalizedDiff === -2) {
|
||||
return 'far-left-item'; // Far left
|
||||
} else if (normalizedDiff === 2) {
|
||||
return 'far-right-item'; // Far right
|
||||
} else {
|
||||
return 'hidden-item'; // Hidden
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="relative py-4 px-4 bg-white">
|
||||
<div className="container mx-auto">
|
||||
{/* Carousel Container */}
|
||||
<div className="relative flex items-center justify-center min-h-[380px]">
|
||||
{/* Carousel Items */}
|
||||
<div className="relative w-full max-w-6xl h-[400px] flex items-center justify-center">
|
||||
{/* Left Arrow - positioned next to center item */}
|
||||
<button
|
||||
onClick={handlePrev}
|
||||
className="absolute left-1/2 -translate-x-[220px] z-30 transition-all duration-200 hover:scale-110"
|
||||
aria-label="Previous"
|
||||
>
|
||||
<img
|
||||
src="/images/flecha-izq.png"
|
||||
alt="Previous"
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
</button>
|
||||
{items.map((item, index) => {
|
||||
const positionClass = getPositionClass(index);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={item.id}
|
||||
className={`carousel-item ${positionClass}`}
|
||||
onClick={() => activeIndex === index && handleItemClick(item.url)}
|
||||
>
|
||||
{/* Circular Image Container */}
|
||||
<div className="relative">
|
||||
{/* Circle with gradient background */}
|
||||
<div className="circle-container">
|
||||
<div className="circle-inner">
|
||||
{/* Image placeholder with gradient */}
|
||||
<div className="w-full h-full rounded-full bg-gradient-to-br from-gray-200 via-gray-300 to-gray-400 flex items-center justify-center overflow-hidden">
|
||||
<img
|
||||
src={item.img}
|
||||
alt={item.subtitle}
|
||||
className="w-full h-full object-cover"
|
||||
onError={(e) => {
|
||||
// Fallback if image doesn't load
|
||||
e.target.style.display = 'none';
|
||||
e.target.parentElement.innerHTML = `
|
||||
<div class="w-full h-full flex items-center justify-center bg-gradient-to-br from-banorte-blue to-banorte-red">
|
||||
<span class="text-white text-2xl font-bold">${item.subtitle.charAt(0)}</span>
|
||||
</div>
|
||||
`;
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Text Below Circle */}
|
||||
<div className="text-center mt-6 space-y-1">
|
||||
<p className="text-banorte-blue font-bold tracking-wide item-title">
|
||||
{item.title}
|
||||
</p>
|
||||
<p className="text-banorte-red font-bold tracking-wider item-subtitle">
|
||||
{item.subtitle}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Right Arrow - positioned next to center item */}
|
||||
<button
|
||||
onClick={handleNext}
|
||||
className="absolute left-1/2 translate-x-[168px] z-30 transition-all duration-200 hover:scale-110"
|
||||
aria-label="Next"
|
||||
>
|
||||
<img
|
||||
src="/images/flecha-der.png"
|
||||
alt="Next"
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Carousel;
|
||||
36
src/components/Header.jsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
|
||||
const Header = () => {
|
||||
return (
|
||||
<header className="bg-banorte-red text-white shadow-lg border-b-4 border-banorte-red">
|
||||
<div className="max-w-[1700px] mx-auto px-4 md:px-6 lg:px-8 py-1 flex items-center justify-between">
|
||||
{/* Logo Section */}
|
||||
<div className="flex items-center">
|
||||
<img
|
||||
src="/images/banortelogo.png"
|
||||
alt="Banorte Logo"
|
||||
className="h-10 w-auto"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* User Section
|
||||
<div className="group relative flex items-center space-x-3 bg-white/10 hover:bg-white/20 backdrop-blur-sm px-4 py-2 rounded-full cursor-pointer transition-all duration-300 hover:shadow-lg">
|
||||
<div className="flex flex-col items-end">
|
||||
<span className="text-xs text-white/70 font-light">Usuario</span>
|
||||
<span className="text-sm md:text-base font-semibold text-white">A8072846</span>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<img
|
||||
src="/images/chat_maya_default_avatar.png"
|
||||
alt="Usuario"
|
||||
className="w-10 h-10 md:w-12 md:h-12 rounded-full border-3 border-white shadow-lg group-hover:scale-110 transition-transform duration-300"
|
||||
/>
|
||||
<div className="absolute bottom-0 right-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white"></div>
|
||||
</div>
|
||||
</div>*/}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
17
src/components/Hero.jsx
Normal file
@@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
|
||||
const Hero = () => {
|
||||
return (
|
||||
<section className="relative w-full px-4 md:px-6 lg:px-8 pt-6 pb-3">
|
||||
<div className="relative max-w-[1150px] mx-auto h-[320px] md:h-[360px] overflow-hidden rounded-3xl shadow-2xl bg-gradient-to-b from-gray-900 via-red-950 to-gray-900">
|
||||
<img
|
||||
src="/images/hero_0.png"
|
||||
alt="Maya Contigo"
|
||||
className="w-full h-full object-fill rounded-3xl"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Hero;
|
||||
58
src/data/modules.js
Normal file
@@ -0,0 +1,58 @@
|
||||
export const modules = [
|
||||
{
|
||||
id: 1,
|
||||
title: "MAYA CONTIGO",
|
||||
subtitle: "EGRESOS",
|
||||
img: "/images/rh.png",
|
||||
url: "https://playground.app.ia-innovacion.work/"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "MAYA CONTIGO",
|
||||
subtitle: "NORMATIVA",
|
||||
img: "/images/normativa.png",
|
||||
url: "https://example.com/normativa"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "MAYA CONTIGO",
|
||||
subtitle: "BURSATIL",
|
||||
img: "/images/pruebas.png",
|
||||
url: "https://example.com/cx"
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "MAYA CONTIGO",
|
||||
subtitle: "INVERSIONISTAS",
|
||||
img: "/images/riesgos.png",
|
||||
url: "https://example.com/bursatil"
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: "MAYA CONTIGO",
|
||||
subtitle: "OCP",
|
||||
img: "/images/normativa.png",
|
||||
url: "https://example.com/pyme"
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: "MAYA CONTIGO",
|
||||
subtitle: "PYME",
|
||||
img: "/images/pruebas.png",
|
||||
url: "https://example.com/pyme"
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
title: "MAYA CONTIGO",
|
||||
subtitle: "RIESGOS",
|
||||
img: "/images/rh.png",
|
||||
url: "https://example.com/pyme"
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
title: "MAYA CONTIGO",
|
||||
subtitle: "CX",
|
||||
img: "/images/normativa.png",
|
||||
url: "https://example.com/pyme"
|
||||
}
|
||||
];
|
||||
27
src/index.css
Normal file
@@ -0,0 +1,27 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
body {
|
||||
@apply bg-white text-gray-900 antialiased;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.text-shadow-red {
|
||||
text-shadow: 0 0 20px rgba(200, 16, 46, 0.5);
|
||||
}
|
||||
|
||||
.shadow-red-glow {
|
||||
box-shadow: 0 0 40px rgba(200, 16, 46, 0.3);
|
||||
}
|
||||
|
||||
.shadow-red-strong {
|
||||
box-shadow: 0 8px 32px rgba(200, 16, 46, 0.4);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-height: 750px){
|
||||
body{zoom: 0.8;}
|
||||
}
|
||||
10
src/main.jsx
Normal file
@@ -0,0 +1,10 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App.jsx'
|
||||
import './index.css'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
19
tailwind.config.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: [
|
||||
"./index.html",
|
||||
"./src/**/*.{js,ts,jsx,tsx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
'banorte-red': '#C8102E',
|
||||
'banorte-blue': '#001A4D',
|
||||
},
|
||||
fontFamily: {
|
||||
'sans': ['Inter', 'system-ui', 'sans-serif'],
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
14
vite.config.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
host: true,
|
||||
allowedHosts: [
|
||||
'5173--main--sebastian--sebastian--sfkl73v7pva4g.pit-1.try.coder.app',
|
||||
'.coder.app',
|
||||
'localhost'
|
||||
]
|
||||
}
|
||||
})
|
||||