Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71c8752eeb | ||
|
|
cda25dea2e | ||
|
|
392a832109 | ||
|
|
a069807960 | ||
|
|
96b08eda01 | ||
|
|
e6c3e0ed8d | ||
|
|
35fdea5df5 | ||
|
|
ef6dc1f6a8 |
No files matched your search
@@ -328,7 +328,69 @@ compartido) para que el contenedor vea los archivos de verdad.
|
|||||||
`<select>` del checkout. Ningún banco PSE real tiene código "0" —
|
`<select>` del checkout. Ningún banco PSE real tiene código "0" —
|
||||||
se filtra explícitamente en `pse-banks/route.ts`.
|
se filtra explícitamente en `pse-banks/route.ts`.
|
||||||
|
|
||||||
### Pendiente — checklist ampliado para la próxima sesión con navegador
|
Ampliado 2026-09-10 con el resto de la superficie real del storefront
|
||||||
|
(4 páginas + `components/{account,cart,catalog,checkout,home,layout,
|
||||||
|
product,search,wishlist}`), agrupado por riesgo, y ejecutado el mismo
|
||||||
|
día contra `shop.cruzcloud.net` con el harness de `.browser-scratch/`.
|
||||||
|
|
||||||
|
### RESUELTO (2026-09-11) — segunda tanda con navegador real
|
||||||
|
|
||||||
|
Resultados reales, uno por uno (código de cada prueba en
|
||||||
|
`checks.mjs`):
|
||||||
|
|
||||||
|
- **`/checkout` con carrito vacío (ítem 9) — OK.** Muestra "Tu carrito
|
||||||
|
está vacío" con link a `/catalog`, no rompe.
|
||||||
|
- **Fallback "Confirmar por WhatsApp" (ítem 10) — OK.** Abre
|
||||||
|
`api.whatsapp.com/send?phone=...` en pestaña nueva con el mensaje del
|
||||||
|
pedido armado correctamente.
|
||||||
|
- **Filtros de `/catalog` (ítem 11) — OK.** Un filtro de categoría real
|
||||||
|
("Figuras de acción") redujo los productos mostrados de 18 a 4. Nota:
|
||||||
|
estos filtros (categoría/marca/edad dentro de la barra lateral) son
|
||||||
|
**estado de cliente, no reflejado en la URL** — distinto de los
|
||||||
|
filtros por query param (`?category=...`) que sí usa la navegación
|
||||||
|
del header. Ninguno de los dos es un bug, son dos mecanismos
|
||||||
|
distintos coexistiendo; queda como nota para no confundirlos.
|
||||||
|
- **Búsqueda sin resultados (ítem 12) — BUG real encontrado y
|
||||||
|
corregido.** El dropdown de autocompletado no mostraba absolutamente
|
||||||
|
nada (ni "Buscando…" ni ningún mensaje) cuando una búsqueda de 2+
|
||||||
|
caracteres no tenía coincidencias — el usuario se quedaba sin
|
||||||
|
feedback de que su búsqueda había corrido. Corregido en
|
||||||
|
`predictive-search.tsx`: ahora muestra "No encontramos resultados
|
||||||
|
para…" con el botón de buscar en todo el catálogo.
|
||||||
|
- **Slug de producto inválido (ítem 14) — hallazgo, no corregido
|
||||||
|
todavía.** La página sí muestra el contenido correcto de "Este tesoro
|
||||||
|
no existe" (el código ya llama a `notFound()` de
|
||||||
|
`next/navigation`, como corresponde), **pero la respuesta HTTP real
|
||||||
|
es `200`, no `404`** — confirmado independientemente con `curl`, no
|
||||||
|
es un artefacto de Playwright. No se investigó a fondo en qué capa se
|
||||||
|
pierde el status real (Next.js standalone vs. alguna capa de
|
||||||
|
Cloudflare/NPM/Traefik en el medio, ver
|
||||||
|
`incidente-cloudflared-504-quic-2026-08.md` para precedente de
|
||||||
|
problemas de red en esa cadena) — bajo impacto en la experiencia del
|
||||||
|
usuario (el contenido es correcto), pero sí afecta SEO/crawlers.
|
||||||
|
Queda como pendiente de investigar, no de corregir a ciegas.
|
||||||
|
- **Zoom interactivo del producto (ítem 15) — OK.** Hover-zoom y el
|
||||||
|
modal de click-to-zoom siguen funcionando igual tras los cambios
|
||||||
|
recientes al storefront.
|
||||||
|
- **Wishlist/favoritos (ítem 17) — OK.** Agregar a favoritos +
|
||||||
|
recargar la página: persiste correctamente vía `localStorage`.
|
||||||
|
- **Otros viewports, tablet y desktop grande (ítem 19) — OK.**
|
||||||
|
Capturas guardadas, sin problemas de layout visibles en el banner ni
|
||||||
|
el header en esos anchos.
|
||||||
|
- **Página 404 genérica (ítem 20) — OK.** Una ruta que no existe cae en
|
||||||
|
`not-found.tsx` con status HTTP `404` real (a diferencia del caso de
|
||||||
|
producto inválido arriba — la diferencia de comportamiento entre
|
||||||
|
ambos casos es justamente lo que quedó como pendiente de investigar).
|
||||||
|
- **Accesibilidad básica (ítem 21) — OK, parcial.** El buscador es
|
||||||
|
alcanzable navegando solo con `Tab` desde el body, sin mouse. Falta
|
||||||
|
probar el resto del flujo de checkout por teclado.
|
||||||
|
- **Registro/login con email y contraseña (parte del ítem 16) — OK.**
|
||||||
|
Crear cuenta con nombre/apellido/email/contraseña funciona y deja la
|
||||||
|
sesión iniciada. La parte de Google OAuth sigue sin probarse (necesita
|
||||||
|
una cuenta de Google real, no algo que se pueda automatizar sin
|
||||||
|
credenciales).
|
||||||
|
|
||||||
|
### Pendiente — lo que queda sin probar
|
||||||
|
|
||||||
3. **Resiliencia del fallback de envío:** forzar una dirección o
|
3. **Resiliencia del fallback de envío:** forzar una dirección o
|
||||||
producto que haga fallar la cotización real de EnvíoClick (ej. un
|
producto que haga fallar la cotización real de EnvíoClick (ej. un
|
||||||
@@ -340,67 +402,26 @@ compartido) para que el contenedor vea los archivos de verdad.
|
|||||||
conseguir credenciales de prueba reales de PSE (persona/clave de
|
conseguir credenciales de prueba reales de PSE (persona/clave de
|
||||||
algún banco del ambiente `desarrollo`), completar el login bancario
|
algún banco del ambiente `desarrollo`), completar el login bancario
|
||||||
de punta a punta, y confirmar que el webhook mueve la orden a
|
de punta a punta, y confirmar que el webhook mueve la orden a
|
||||||
completada sin intervención manual — hoy solo se confirmó que el
|
completada sin intervención manual.
|
||||||
endpoint responde `200` a un `POST` sintético y que la redirección
|
|
||||||
al banco ocurre, no el ciclo completo con notificación real.
|
|
||||||
Ampliado 2026-09-10 con el resto de la superficie real del storefront
|
|
||||||
(4 páginas + `components/{account,cart,catalog,checkout,home,layout,
|
|
||||||
product,search,wishlist}`), agrupado por riesgo:
|
|
||||||
|
|
||||||
**Checkout / pagos**
|
|
||||||
|
|
||||||
7. **Pago cancelado o rechazado en el banco PSE:** confirmar que la
|
7. **Pago cancelado o rechazado en el banco PSE:** confirmar que la
|
||||||
orden no queda en un estado ambiguo ("colgada" en
|
orden no queda en un estado ambiguo ("colgada" en
|
||||||
`pending_authorization` para siempre) cuando el comprador cancela o
|
`pending_authorization` para siempre).
|
||||||
el banco rechaza — hoy solo se probó el camino feliz hasta la
|
|
||||||
redirección.
|
|
||||||
8. **Persona jurídica + NIT** en el formulario de PSE — solo se probó
|
8. **Persona jurídica + NIT** en el formulario de PSE — solo se probó
|
||||||
persona natural con cédula.
|
persona natural con cédula.
|
||||||
9. **`/checkout` con carrito vacío** (acceso directo por URL, sin pasar
|
|
||||||
por un producto primero).
|
|
||||||
10. **Fallback "Confirmar por WhatsApp"** (visible cuando falla la
|
|
||||||
lista de bancos o como alternativa siempre disponible): que el link
|
|
||||||
arme el mensaje correcto con los datos del pedido.
|
|
||||||
|
|
||||||
**Catálogo y búsqueda**
|
|
||||||
|
|
||||||
11. **Filtros de `/catalog`** (categoría/colección/marca/precio — las
|
|
||||||
facetas de Meilisearch, ver ADR 0006) con navegador real: que
|
|
||||||
aplicar/combinar filtros actualice los resultados y la URL.
|
|
||||||
12. **Búsqueda sin resultados** — confirmar que muestra un mensaje
|
|
||||||
claro en vez de quedar vacío sin explicación.
|
|
||||||
|
|
||||||
**Producto**
|
|
||||||
|
|
||||||
13. **Selección de variantes** (cuando un producto tiene más de una) y
|
13. **Selección de variantes** (cuando un producto tiene más de una) y
|
||||||
que el precio/disponibilidad mostrado cambie según la variante
|
que el precio/disponibilidad mostrado cambie según la variante
|
||||||
elegida.
|
elegida — ningún producto probado hasta ahora tenía más de una
|
||||||
14. **Slug de producto inválido** → debe caer en `not-found.tsx`
|
variante real.
|
||||||
(`app/not-found.tsx`), no en un error sin manejar.
|
14b. **Investigar por qué `/product/<slug-inválido>` responde HTTP 200**
|
||||||
15. **Zoom interactivo del producto** (hover + modal click-to-zoom,
|
en vez de 404 pese a llamar `notFound()` correctamente (ver
|
||||||
`product-gallery.tsx`) — re-verificar con navegador real, la última
|
hallazgo arriba) — identificar la capa responsable antes de tocar
|
||||||
vez que se probó fue antes de esta tanda de cambios al storefront.
|
código.
|
||||||
|
16b. **Login con Google (OAuth completo)** incluyendo
|
||||||
**Cuenta y wishlist**
|
`/auth/google/callback` — necesita una cuenta de Google real de
|
||||||
|
prueba.
|
||||||
16. **Login/registro de cliente real** (Google OAuth de punta a punta
|
|
||||||
incluyendo `/auth/google/callback`, y con contraseña) — nunca
|
|
||||||
ejercitado con un navegador real en ninguna sesión.
|
|
||||||
17. **Wishlist/favoritos** (`wishlist-drawer.tsx`): agregar/quitar y
|
|
||||||
confirmar que persiste entre recargas (guardado en `localStorage`,
|
|
||||||
por-viewer — no hay forma de verificarlo por API).
|
|
||||||
|
|
||||||
**Transversal**
|
|
||||||
|
|
||||||
18. **Bug conocido de Firefox Android** (ver memoria de proyecto,
|
18. **Bug conocido de Firefox Android** (ver memoria de proyecto,
|
||||||
`known-bug-firefox-android-layout`): el layout se corta/desplaza
|
`known-bug-firefox-android-layout`) — Playwright puede emular
|
||||||
solo en Firefox Android — Playwright puede emular Android/Chrome
|
Android/Chrome pero no Firefox; hace falta `playwright-firefox` o
|
||||||
pero no Firefox; si se necesita reproducir esto específicamente hace
|
un dispositivo real.
|
||||||
falta `playwright-firefox` o un dispositivo real.
|
21b. **Accesibilidad del checkout completo** por teclado (no solo el
|
||||||
19. **Otros viewports** (tablet, desktop grande) para el banner y el
|
buscador) — tab order y foco visible en los 3 pasos.
|
||||||
buscador — solo se probaron mobile (iPhone 13) y desktop 1280px.
|
|
||||||
20. **Página 404** (`app/not-found.tsx`) — nunca visitada con navegador
|
|
||||||
real.
|
|
||||||
21. **Accesibilidad básica**: navegación completa por teclado (tab
|
|
||||||
order, foco visible) en el checkout y el buscador — Playwright
|
|
||||||
puede simular esto (`page.keyboard`), no probado todavía.
|
|
||||||
@@ -25,7 +25,7 @@ spec:
|
|||||||
runAsNonRoot: false
|
runAsNonRoot: false
|
||||||
containers:
|
containers:
|
||||||
- name: app
|
- name: app
|
||||||
image: gitea.cruzcloud.net/devops/docs-portal:v1.0.241
|
image: gitea.cruzcloud.net/devops/docs-portal:v1.0.244
|
||||||
# El base saca TODAS las capabilities. Probado en vivo y
|
# El base saca TODAS las capabilities. Probado en vivo y
|
||||||
# revertido: con drop: ALL (aunque se agregue NET_BIND_SERVICE
|
# revertido: con drop: ALL (aunque se agregue NET_BIND_SERVICE
|
||||||
# de vuelta) el propio entrypoint de nginx:1.27-alpine falla al
|
# de vuelta) el propio entrypoint de nginx:1.27-alpine falla al
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import type { Metadata } from "next";
|
||||||
|
import { Mail, MapPin, MessageCircle } from "lucide-react";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "Contacto | ARI Shopping" };
|
||||||
|
|
||||||
|
// Numero real confirmado en vivo (probando el boton "Confirmar por
|
||||||
|
// WhatsApp" del checkout con navegador real): mismo canal que ya usan
|
||||||
|
// los clientes para confirmar pedidos, consistencia a proposito.
|
||||||
|
const WHATSAPP_URL = "https://wa.me/573016138155";
|
||||||
|
// Correo corporativo nuevo ([email protected] -> reenviado por
|
||||||
|
// Cloudflare Email Routing a la casilla real) -- ver nota de
|
||||||
|
// implementacion en ADR 0010 para el paso manual de DNS pendiente.
|
||||||
|
const CONTACT_EMAIL = "[email protected]";
|
||||||
|
|
||||||
|
export default function ContactoPage() {
|
||||||
|
return (
|
||||||
|
<section className="mx-auto max-w-2xl px-4 py-14 text-center lg:py-20">
|
||||||
|
<span className="text-xs font-black uppercase tracking-[.18em] text-ari-coral">Ayuda</span>
|
||||||
|
<h1 className="mt-3 text-4xl font-black tracking-tight sm:text-5xl">Contacto</h1>
|
||||||
|
<p className="mt-5 text-lg leading-8 text-slate-600">
|
||||||
|
¿Tenés una pregunta sobre tu pedido, un producto o un cambio? Escribinos, te respondemos lo antes posible.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="mt-10 grid gap-4 sm:grid-cols-2">
|
||||||
|
<a
|
||||||
|
href={WHATSAPP_URL}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex flex-col items-center gap-3 rounded-2xl border border-slate-200 p-6 transition hover:border-ari-marino hover:bg-ari-marino/5"
|
||||||
|
>
|
||||||
|
<MessageCircle className="size-7 text-ari-marino" />
|
||||||
|
<div>
|
||||||
|
<p className="font-black">WhatsApp</p>
|
||||||
|
<p className="mt-1 text-sm text-slate-500">+57 301 613 8155</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href={`mailto:${CONTACT_EMAIL}`}
|
||||||
|
className="flex flex-col items-center gap-3 rounded-2xl border border-slate-200 p-6 transition hover:border-ari-marino hover:bg-ari-marino/5"
|
||||||
|
>
|
||||||
|
<Mail className="size-7 text-ari-marino" />
|
||||||
|
<div>
|
||||||
|
<p className="font-black">Correo</p>
|
||||||
|
<p className="mt-1 text-sm text-slate-500">{CONTACT_EMAIL}</p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-10 flex items-center justify-center gap-2 text-sm text-slate-500">
|
||||||
|
<MapPin className="size-4" />
|
||||||
|
Despachamos desde Bogotá D.C., Colombia
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button asChild variant="primary" size="lg" className="mt-10">
|
||||||
|
<a href={WHATSAPP_URL} target="_blank" rel="noopener noreferrer">
|
||||||
|
<MessageCircle className="size-5" />
|
||||||
|
Escribirnos por WhatsApp
|
||||||
|
</a>
|
||||||
|
</Button>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import type { Metadata } from "next";
|
||||||
|
import { Calculator, Clock, MapPinned, Truck } from "lucide-react";
|
||||||
|
|
||||||
|
export const metadata: Metadata = { title: "Envíos | ARI Shopping" };
|
||||||
|
|
||||||
|
// ADR 0010 §2: el costo de envio se calcula en vivo con EnvioClick (peso +
|
||||||
|
// direccion), no es un valor fijo -- el copy de abajo describe ese
|
||||||
|
// comportamiento real, no un placeholder. Transportadoras reales
|
||||||
|
// confirmadas en una cotizacion en vivo contra la API de EnvioClick
|
||||||
|
// (PIBOX, COORDINADORA, ENVIA, RAPPI, TCC) -- EnvioClick cotiza entre
|
||||||
|
// ellas y el sistema toma automaticamente la mas economica por pedido.
|
||||||
|
const CARRIERS = ["Coordinadora", "Envía", "TCC", "Rappi", "Pibox"];
|
||||||
|
|
||||||
|
export default function EnviosPage() {
|
||||||
|
return (
|
||||||
|
<section className="mx-auto max-w-3xl px-4 py-14 lg:py-20">
|
||||||
|
<span className="text-xs font-black uppercase tracking-[.18em] text-ari-coral">Ayuda</span>
|
||||||
|
<h1 className="mt-3 text-4xl font-black tracking-tight sm:text-5xl">Envíos</h1>
|
||||||
|
<p className="mt-5 text-lg leading-8 text-slate-600">
|
||||||
|
Hacemos envíos a nivel nacional desde nuestra bodega en Bogotá D.C.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="mt-10 grid gap-6 sm:grid-cols-2">
|
||||||
|
<div className="rounded-2xl border border-slate-200 p-6">
|
||||||
|
<Calculator className="size-6 text-ari-marino" />
|
||||||
|
<h2 className="mt-3 font-black">Costo calculado en tiempo real</h2>
|
||||||
|
<p className="mt-2 text-sm leading-6 text-slate-600">
|
||||||
|
El valor del envío se calcula automáticamente según el peso de tu pedido y la dirección de entrega —
|
||||||
|
lo ves exacto en el checkout antes de pagar, nunca es una tarifa a ciegas.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-2xl border border-slate-200 p-6">
|
||||||
|
<Truck className="size-6 text-ari-marino" />
|
||||||
|
<h2 className="mt-3 font-black">Transportadoras aliadas</h2>
|
||||||
|
<p className="mt-2 text-sm leading-6 text-slate-600">
|
||||||
|
Cotizamos automáticamente entre {CARRIERS.join(", ")} y asignamos la tarifa más conveniente para cada
|
||||||
|
pedido.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-2xl border border-slate-200 p-6">
|
||||||
|
<Clock className="size-6 text-ari-marino" />
|
||||||
|
<h2 className="mt-3 font-black">Tiempos de entrega</h2>
|
||||||
|
<p className="mt-2 text-sm leading-6 text-slate-600">
|
||||||
|
Varían según la transportadora asignada y tu ciudad — una vez despachado tu pedido te compartimos el
|
||||||
|
número de guía para hacerle seguimiento.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-2xl border border-slate-200 p-6">
|
||||||
|
<MapPinned className="size-6 text-ari-marino" />
|
||||||
|
<h2 className="mt-3 font-black">Cobertura</h2>
|
||||||
|
<p className="mt-2 text-sm leading-6 text-slate-600">
|
||||||
|
Envíos a todo el territorio nacional colombiano desde nuestra bodega en Bogotá D.C.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="mt-10 text-sm text-slate-500">
|
||||||
|
¿Tenés dudas puntuales sobre un pedido? Escribinos por{" "}
|
||||||
|
<a href="/contacto" className="font-bold text-ari-marino hover:underline">
|
||||||
|
nuestros canales de contacto
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,10 +1,30 @@
|
|||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Facebook, Instagram, MessageCircle } from "lucide-react";
|
import { Facebook, Instagram, MessageCircle } from "lucide-react";
|
||||||
|
|
||||||
|
// "Envíos" y "Contacto" ya tienen paginas reales (app/envios,
|
||||||
|
// app/contacto -- contenido real: transportadoras de EnvioClick,
|
||||||
|
// WhatsApp/correo reales). "Preguntas frecuentes" y "Cambios" todavia
|
||||||
|
// no tienen contenido real decidido -- quedan apuntando a /catalog
|
||||||
|
// (no rotas, pero tampoco resueltas) hasta que se defina que van a
|
||||||
|
// decir.
|
||||||
|
const HELP_LINKS = [
|
||||||
|
{ label: "Preguntas frecuentes", href: "/catalog" },
|
||||||
|
{ label: "Envíos", href: "/envios" },
|
||||||
|
{ label: "Cambios", href: "/catalog" },
|
||||||
|
{ label: "Contacto", href: "/contacto" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const SHOP_LINKS = [
|
||||||
|
{ label: "Novedades", href: "/catalog" },
|
||||||
|
{ label: "Juguetes", href: "/catalog" },
|
||||||
|
{ label: "Mochilas", href: "/catalog" },
|
||||||
|
{ label: "Regalos", href: "/catalog" },
|
||||||
|
];
|
||||||
|
|
||||||
export function Footer() {
|
export function Footer() {
|
||||||
return <footer className="bg-ari-marino text-white"><div className="mx-auto grid max-w-7xl gap-10 px-4 py-14 sm:grid-cols-2 lg:grid-cols-4"><div><div className="flex flex-col items-start gap-3"><img src="/images/brand/logo-ari.svg" alt="ARI shopping" className="h-11 w-auto" width={200} height={64} />{/* eslint-disable-line @next/next/no-img-element -- vector propio, next/image no optimiza SVG sin habilitar dangerouslyAllowSVG */}<p className="text-xs text-white/60">Tesoros para cada aventura.</p></div><div className="mt-5 flex gap-3"><Instagram /><Facebook /><MessageCircle /></div></div><FooterColumn title="Compra" links={["Novedades", "Juguetes", "Mochilas", "Regalos"]} /><FooterColumn title="Ayuda" links={["Preguntas frecuentes", "Envíos", "Cambios", "Contacto"]} /><div><h3 className="font-black">Newsletter</h3><p className="mt-3 text-sm leading-6 text-white/60">Recibe lanzamientos y promociones especiales.</p><div className="mt-4 flex rounded-full bg-white p-1"><input className="min-w-0 flex-1 bg-transparent px-4 text-sm text-slate-950 outline-none" placeholder="Tu correo" /><button className="rounded-full bg-ari-coral px-4 text-sm font-black text-white">Unirme</button></div></div></div><div className="border-t border-white/10 py-5 text-center text-xs text-white/50">© 2026 ARI Shopping · Frontend headless v4.1 · GitOps</div></footer>;
|
return <footer className="bg-ari-marino text-white"><div className="mx-auto grid max-w-7xl gap-10 px-4 py-14 sm:grid-cols-2 lg:grid-cols-4"><div><div className="flex flex-col items-start gap-3"><img src="/images/brand/logo-ari.svg" alt="ARI shopping" className="h-11 w-auto" width={200} height={64} />{/* eslint-disable-line @next/next/no-img-element -- vector propio, next/image no optimiza SVG sin habilitar dangerouslyAllowSVG */}<p className="text-xs text-white/60">Tesoros para cada aventura.</p></div><div className="mt-5 flex gap-3"><Instagram /><Facebook /><MessageCircle /></div></div><FooterColumn title="Compra" links={SHOP_LINKS} /><FooterColumn title="Ayuda" links={HELP_LINKS} /><div><h3 className="font-black">Newsletter</h3><p className="mt-3 text-sm leading-6 text-white/60">Recibe lanzamientos y promociones especiales.</p><div className="mt-4 flex rounded-full bg-white p-1"><input className="min-w-0 flex-1 bg-transparent px-4 text-sm text-slate-950 outline-none" placeholder="Tu correo" /><button className="rounded-full bg-ari-coral px-4 text-sm font-black text-white">Unirme</button></div></div></div><div className="border-t border-white/10 py-5 text-center text-xs text-white/50">© 2026 ARI Shopping · Frontend headless v4.1 · GitOps</div></footer>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function FooterColumn({ title, links }: { title: string; links: string[] }) {
|
function FooterColumn({ title, links }: { title: string; links: { label: string; href: string }[] }) {
|
||||||
return <div><h3 className="font-black">{title}</h3><div className="mt-4 grid gap-3 text-sm text-white/60">{links.map((link) => <Link key={link} href="/catalog" className="hover:text-ari-coral-claro">{link}</Link>)}</div></div>;
|
return <div><h3 className="font-black">{title}</h3><div className="mt-4 grid gap-3 text-sm text-white/60">{links.map((link) => <Link key={link.label} href={link.href} className="hover:text-ari-coral-claro">{link.label}</Link>)}</div></div>;
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ spec:
|
|||||||
runAsUser: 1001
|
runAsUser: 1001
|
||||||
containers:
|
containers:
|
||||||
- name: app
|
- name: app
|
||||||
image: gitea.cruzcloud.net/devops/ecommerce-frontend:v1.0.240
|
image: gitea.cruzcloud.net/devops/ecommerce-frontend:v1.0.243
|
||||||
env:
|
env:
|
||||||
- name: HEADLESS_PROVIDER
|
- name: HEADLESS_PROVIDER
|
||||||
value: medusa
|
value: medusa
|
||||||
|
|||||||
Reference in new issue
Block a user