all changes
This commit is contained in:
1 parent
cba8d4055b
commit
9dfced04f1
103 files changed
+7378
-31250
No files matched your search
@@ -0,0 +1,177 @@
|
||||
"use client";
|
||||
import { motion } from "framer-motion";
|
||||
import Loader from "../components/Loader";
|
||||
import { useProducts } from "../services/products";
|
||||
import { assetUrl } from "../services/api";
|
||||
import type { ThemeProps } from "../types";
|
||||
|
||||
export const Showcase = ({ isNavyBg }: ThemeProps) => {
|
||||
const { data, isLoading } = useProducts();
|
||||
|
||||
const products = (data ?? []).filter((p) => p.isActive);
|
||||
|
||||
const bg = isNavyBg ? "#080c14" : "#f0efec";
|
||||
const text = isNavyBg ? "#ffffff" : "#0a0a0a";
|
||||
const sub = isNavyBg ? "rgba(255,255,255,0.45)" : "#6a6866";
|
||||
const border = isNavyBg ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.08)";
|
||||
const tagBg = isNavyBg ? "rgba(59,130,246,0.1)" : "rgba(59,130,246,0.07)";
|
||||
|
||||
return (
|
||||
<section
|
||||
id="showcase"
|
||||
aria-labelledby="showcase-heading"
|
||||
style={{
|
||||
background: bg,
|
||||
color: text,
|
||||
borderBottom: `1px solid ${border}`,
|
||||
}}
|
||||
className="px-8 py-28 md:px-14 transition-colors duration-500"
|
||||
>
|
||||
<div className="mx-auto max-w-7xl">
|
||||
<motion.div
|
||||
className="mb-16"
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true }}
|
||||
transition={{ duration: 0.6, ease: [0.22, 1, 0.36, 1] }}
|
||||
>
|
||||
<span
|
||||
className="mb-3 block text-xs font-semibold uppercase tracking-[0.14em]"
|
||||
style={{ color: "#3b82f6" }}
|
||||
>
|
||||
Lo que construimos
|
||||
</span>
|
||||
<h2
|
||||
id="showcase-heading"
|
||||
className="text-headline"
|
||||
style={{ maxWidth: "28ch" }}
|
||||
>
|
||||
Sistemas reales para operaciones reales.
|
||||
</h2>
|
||||
<p
|
||||
className="mt-4 max-w-xl text-base leading-relaxed"
|
||||
style={{ color: sub }}
|
||||
>
|
||||
No plantillas ni demos genéricos. Cada sistema sale de entender la
|
||||
operación y construir la arquitectura correcta desde cero.
|
||||
</p>
|
||||
</motion.div>
|
||||
|
||||
{isLoading ? (
|
||||
<Loader className="py-20" />
|
||||
) : products.length > 0 ? (
|
||||
<div className="grid gap-6 lg:grid-cols-3">
|
||||
{products.map(({ id, imageUrl, name, description, badges }, i) => (
|
||||
<motion.article
|
||||
key={id}
|
||||
initial={{ opacity: 0, y: 24 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-40px" }}
|
||||
transition={{
|
||||
duration: 0.55,
|
||||
delay: i * 0.1,
|
||||
ease: [0.22, 1, 0.36, 1],
|
||||
}}
|
||||
style={{
|
||||
borderRadius: 14,
|
||||
border: `1px solid ${border}`,
|
||||
background: isNavyBg ? "rgba(255,255,255,0.03)" : "#ffffff",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
background: isNavyBg
|
||||
? "rgba(255,255,255,0.04)"
|
||||
: "rgba(0,0,0,0.03)",
|
||||
borderBottom: `1px solid ${border}`,
|
||||
aspectRatio: "16/9",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{imageUrl ? (
|
||||
<img
|
||||
src={assetUrl(imageUrl)}
|
||||
alt={name}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
objectFit: "cover",
|
||||
display: "block",
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke={sub}
|
||||
strokeWidth="1.5"
|
||||
>
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" />
|
||||
<circle cx="8.5" cy="8.5" r="1.5" />
|
||||
<path d="m21 15-5-5L5 21" />
|
||||
</svg>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ padding: "24px 24px 28px" }}>
|
||||
<h3
|
||||
className="font-display font-bold mb-2"
|
||||
style={{
|
||||
fontSize: "1.05rem",
|
||||
color: text,
|
||||
letterSpacing: "-0.01em",
|
||||
}}
|
||||
>
|
||||
{name}
|
||||
</h3>
|
||||
<p
|
||||
className="text-sm leading-relaxed mb-5"
|
||||
style={{ color: sub }}
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
{badges && badges.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{badges.map((badge) => (
|
||||
<span
|
||||
key={badge}
|
||||
style={{
|
||||
fontSize: 10.5,
|
||||
fontWeight: 600,
|
||||
padding: "3px 9px",
|
||||
borderRadius: 99,
|
||||
background: tagBg,
|
||||
color: "#3b82f6",
|
||||
letterSpacing: "0.01em",
|
||||
}}
|
||||
>
|
||||
{badge}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</motion.article>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm" style={{ color: sub }}>
|
||||
Sin productos registrados.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
Reference in new issue
Block a user