Files
Landing/src/app/sobre-nosotros/SobreNosotrosPage.tsx
T
2026-08-28 21:17:22 -05:00

180 lines
10 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
import { motion } from 'framer-motion';
import Loader from '../../components/Loader';
import { useTeam, groupByDepartment } from '../../services/team';
import { valores, porQueRynext } from '../../data/sobreNosotrosData';
const TEAM_IMAGE = 'https://images.unsplash.com/photo-1522071820081-009f0129c71c?w=1200&q=80';
function SobreNosotrosContent() {
const { data: members, isLoading: loadingTeam } = useTeam();
const departments = groupByDepartment(members ?? []);
useEffect(() => {
document.title = 'Sobre Nosotros | Rynext Technologies';
}, []);
return (
<main id="main-content">
{/* Hero */}
<section
style={{ background: '#ffffff', borderBottom: '1px solid #dddbd5', paddingTop: '140px', paddingBottom: '100px' }}
className="px-8 md:px-14"
>
<div className="mx-auto max-w-7xl grid gap-16 lg:grid-cols-2 lg:items-center">
<div>
<motion.h1
className="text-display mb-8"
style={{ color: '#0a0a0a' }}
initial="hidden" whileInView="visible" viewport={{ once: true }}
variants={{ hidden: { opacity: 0, y: 32 }, visible: { opacity: 1, y: 0, transition: { duration: 0.7, delay: 0.1, ease: [0.22, 1, 0.36, 1] } } }}
>
Software 100%{' '}
<span style={{ position: 'relative', display: 'inline-block' }}>
<span style={{ color: '#3b82f6' }}>Mexicano</span>
<svg viewBox="0 0 200 12" preserveAspectRatio="none" aria-hidden="true"
style={{ position: 'absolute', bottom: -4, left: 0, width: '100%', height: 12 }}>
<path d="M2 8 C50 2, 150 2, 198 8" stroke="#3b82f6" strokeWidth="3" strokeLinecap="round" fill="none" />
</svg>
</span>{' '}
de clase mundial.
</motion.h1>
<motion.p className="text-lg leading-relaxed" style={{ color: '#6a6866' }}
initial="hidden" whileInView="visible" viewport={{ once: true }}
variants={{ hidden: { opacity: 0, y: 24 }, visible: { opacity: 1, y: 0, transition: { duration: 0.6, delay: 0.2, ease: [0.22, 1, 0.36, 1] } } }}>
Rynext Technologies nació de una convicción: México tiene el talento para construir
software empresarial que compita con cualquier firma en el mundo. No adaptamos
herramientas extranjeras diseñamos sistemas propios, con las tecnologías más
actuales, para la realidad operativa de los negocios mexicanos.
</motion.p>
</div>
<motion.div initial="hidden" whileInView="visible" viewport={{ once: true }}
variants={{ hidden: { opacity: 0, x: 24 }, visible: { opacity: 1, x: 0, transition: { duration: 0.7, delay: 0.15, ease: [0.22, 1, 0.36, 1] } } }}
style={{ position: 'relative' }}>
<div style={{ position: 'absolute', top: 16, left: -16, width: '100%', height: '100%', border: '3px solid #3b82f6', borderRadius: 2, zIndex: 0 }} />
<img src={TEAM_IMAGE} alt="Equipo Rynext Technologies"
style={{ position: 'relative', zIndex: 1, width: '100%', aspectRatio: '4/3', objectFit: 'cover', display: 'block', clipPath: 'polygon(0 0, 100% 0, 100% 88%, 94% 100%, 0 100%)' }}
/>
</motion.div>
</div>
</section>
{/* Por qué Rynext */}
<section style={{ background: '#f5f5f3', borderBottom: '1px solid #dddbd5', padding: '100px 0' }} className="px-8 md:px-14">
<div className="mx-auto max-w-7xl">
<motion.h2 className="text-display mb-20" style={{ color: '#0a0a0a', maxWidth: '22ch' }}
initial="hidden" whileInView="visible" viewport={{ once: true }}
variants={{ hidden: { opacity: 0, y: 28 }, visible: { opacity: 1, y: 0, transition: { duration: 0.7, ease: [0.22, 1, 0.36, 1] } } }}>
¿Por qué <span style={{ color: '#3b82f6' }}>Rynext Technologies?</span>
</motion.h2>
<div className="flex flex-col divide-y" style={{ borderTop: '1px solid #dddbd5', borderBottom: '1px solid #dddbd5' }}>
{porQueRynext.map((item, i) => (
<motion.div key={i}
initial="hidden" whileInView="visible" viewport={{ once: true }}
variants={{ hidden: { opacity: 0, y: 16 }, visible: { opacity: 1, y: 0, transition: { duration: 0.5, delay: i * 0.08, ease: [0.22, 1, 0.36, 1] } } }}
className="grid py-10 md:grid-cols-[80px_1fr_2fr] gap-6 items-start"
style={{ borderColor: '#dddbd5' }}>
<span className="font-display font-black" style={{ fontSize: 48, lineHeight: 1, color: '#3b82f6', letterSpacing: '-0.04em' }}>{item.num}</span>
<h3 className="font-display font-bold text-xl" style={{ color: '#0a0a0a' }}>{item.titulo}</h3>
<p className="text-base leading-relaxed" style={{ color: '#6a6866', maxWidth: '52ch' }}>{item.desc}</p>
</motion.div>
))}
</div>
</div>
</section>
{/* Valores */}
<section style={{ background: '#ffffff', borderBottom: '1px solid #dddbd5', padding: '100px 0' }} className="px-8 md:px-14">
<div className="mx-auto max-w-7xl">
<motion.h2 className="text-headline mb-16" style={{ color: '#0a0a0a' }}
initial="hidden" whileInView="visible" viewport={{ once: true }}
variants={{ hidden: { opacity: 0, y: 28 }, visible: { opacity: 1, y: 0, transition: { duration: 0.6, delay: 0.1, ease: [0.22, 1, 0.36, 1] } } }}>
Los principios que guían cada proyecto.
</motion.h2>
<div className="grid gap-8 md:grid-cols-5">
{valores.map((v, i) => (
<motion.div key={i}
initial="hidden" whileInView="visible" viewport={{ once: true }}
variants={{ hidden: { opacity: 0, y: 20 }, visible: { opacity: 1, y: 0, transition: { duration: 0.5, delay: i * 0.08, ease: [0.22, 1, 0.36, 1] } } }}
style={{ borderTop: '3px solid #3b82f6', paddingTop: 24 }}>
<span className="font-display font-black block mb-4" style={{ fontSize: 48, lineHeight: 1, color: '#3b82f6', letterSpacing: '-0.04em' }}>{v.num}</span>
<h3 className="font-display font-bold text-base mb-3" style={{ color: '#0a0a0a' }}>{v.titulo}</h3>
<p className="text-sm leading-relaxed" style={{ color: '#6a6866' }}>{v.desc}</p>
</motion.div>
))}
</div>
</div>
</section>
{/* Equipo */}
<section style={{ background: '#f5f5f3', borderBottom: '1px solid #dddbd5', padding: '100px 0' }} className="px-8 md:px-14">
<div className="mx-auto max-w-7xl">
<motion.h2 className="text-headline mb-16" style={{ color: '#0a0a0a' }}
initial={{ opacity: 0, y: 24 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }}
transition={{ duration: 0.6, ease: [0.22, 1, 0.36, 1] }}>
El equipo detrás del código.
</motion.h2>
{loadingTeam ? (
<Loader className="py-16" />
) : departments.length === 0 ? (
<p className="text-sm" style={{ color: '#aaa8a4' }}>Sin miembros registrados.</p>
) : (
<div className="flex flex-col gap-14">
{departments.map((dept, di) => (
<motion.div key={dept.name}
initial={{ opacity: 0, y: 20 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }}
transition={{ duration: 0.5, delay: di * 0.08, ease: [0.22, 1, 0.36, 1] }}>
{/* Dept header */}
<div className="flex items-center gap-3 mb-0">
<span style={{ width: 3, height: 16, background: '#3b82f6', borderRadius: 99, flexShrink: 0, display: 'block' }} />
<p className="text-xs font-semibold uppercase tracking-widest" style={{ color: '#6a6866' }}>
{dept.name}
</p>
</div>
{/* Hierarchy connector */}
<div style={{ position: 'relative', paddingLeft: 20, marginLeft: 1 }}>
{/* Vertical line */}
<span style={{ position: 'absolute', left: 0, top: 0, bottom: 24, width: 1, background: '#dddbd5' }} />
{/* Horizontal branch */}
<span style={{ position: 'absolute', left: 0, top: 24, width: 16, height: 1, background: '#dddbd5' }} />
<div className="grid gap-3 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 pt-6">
{dept.members.map((m, mi) => (
<motion.div key={m.id}
initial={{ opacity: 0, y: 12 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true }}
transition={{ duration: 0.4, delay: mi * 0.05, ease: [0.22, 1, 0.36, 1] }}
style={{ background: '#ffffff', borderRadius: 6, padding: '20px', display: 'flex', alignItems: 'center', gap: 14, boxShadow: '0 1px 3px rgba(0,0,0,0.07)' }}>
<div style={{ width: 44, height: 44, borderRadius: '50%', background: 'linear-gradient(135deg,#3b82f6,#1d4ed8)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ color: '#fff', fontWeight: 700, fontSize: 14, letterSpacing: '0.02em' }}>{m.firstName[0]}{m.lastName[0]}</span>
</div>
<div style={{ minWidth: 0 }}>
<p className="font-display font-bold text-sm" style={{ color: '#0a0a0a', lineHeight: 1.3, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{m.firstName} {m.lastName}</p>
{m.positionName && <p className="text-xs mt-0.5" style={{ color: '#9ca3af' }}>{m.positionName}</p>}
</div>
</motion.div>
))}
</div>
</div>
</motion.div>
))}
</div>
)}
</div>
</section>
</main>
);
}
export function SobreNosotrosPage() {
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
if (!mounted) return null;
return <SobreNosotrosContent />;
}