This commit is contained in:
Emmanuel Rojas committed 2026-10-06 02:00:11 -05:00
1 parent 794a659369
commit 5f99b65611
349 files changed
+32252 -2180

No files matched your search

@@ -0,0 +1,90 @@
"use client";
import { useState, useEffect } from "react";
import { motion } from "framer-motion";
import Loader from '@/app/(landing)/components/Loader';
import { useCompanies } from '@/app/(landing)/home/services/companies';
import { assetUrl } from '@/app/(landing)/services/api';
import type { ThemeProps } from '@/app/(landing)/types/ui';
function ClientsInner({ isNavyBg }: ThemeProps) {
const { data, isLoading } = useCompanies();
const bg = isNavyBg ? "var(--background)" : "#f0efec";
const border = isNavyBg ? "rgba(255,255,255,0.07)" : "rgba(0,0,0,0.07)";
const label = isNavyBg ? "rgba(255,255,255,0.28)" : "rgba(0,0,0,0.28)";
const companies = (data ?? []).filter((c) => c.showInLanding && c.logoUrl);
if (isLoading) {
return (
<section
style={{ background: bg, borderBottom: `1px solid ${border}` }}
className="px-8 py-14 md:px-14"
>
<Loader className="py-8" />
</section>
);
}
if (companies.length === 0) return null;
return (
<section
aria-label="Empresas que confían en Rynext"
style={{ background: bg, borderBottom: `1px solid ${border}` }}
className="px-8 py-14 md:px-14 transition-colors duration-500"
>
<motion.div
className="mx-auto max-w-7xl"
initial={{ opacity: 0, y: 16 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.6, ease: [0.22, 1, 0.36, 1] }}
>
<p
className="mb-10 text-center text-xs font-semibold uppercase tracking-[0.18em]"
style={{ color: label }}
>
Empresas que confían en Rynext
</p>
<div className="flex flex-wrap items-center justify-center gap-10 md:gap-16">
{companies.map((c) => (
<div key={c.id} title={c.name} style={{ lineHeight: 1 }}>
<img
src={assetUrl(c.logoUrl)}
alt={c.name}
style={{
height: 150,
width: "auto",
maxWidth: 200,
objectFit: "contain",
// grayscale solo: invert+brightness(0) aplanaba logos a color
// (fotos/JPEG) a un bloque negro o blanco ilegible en dark.
filter: "grayscale(1)",
opacity: 0.55,
transition: "opacity 250ms",
}}
onError={(e) => {
(e.currentTarget as HTMLImageElement).style.display = "none";
}}
onMouseEnter={(e) =>
((e.currentTarget as HTMLImageElement).style.opacity = "1")
}
onMouseLeave={(e) =>
((e.currentTarget as HTMLImageElement).style.opacity = "0.6")
}
/>
</div>
))}
</div>
</motion.div>
</section>
);
}
export const Clients = (props: ThemeProps) => {
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
if (!mounted) return null;
return <ClientsInner {...props} />;
};