Autosave: 20260501-144609

This commit is contained in:
Flatlogic Bot 2026-05-01 14:46:07 +00:00
parent e46cec7f80
commit ba7bba35d1
12 changed files with 171 additions and 176 deletions

View File

@ -90,18 +90,18 @@ export default function PublicShell({ activeSection, children, floatingAction }:
<div className="mb-4 inline-flex items-center gap-2 rounded-full border border-[#DAA520]/40 bg-[#DAA520]/10 px-3 py-1 text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">
Chinchorreo PR
</div>
<h1 className="text-3xl font-black tracking-tight text-white">Guía boricua para salir a chinchorrear</h1>
<h1 className="text-3xl font-black tracking-tight text-white">La guía boricua para cuadrar un buen chinchorreo</h1>
<p className="mt-3 text-sm leading-6 text-slate-300">
Rutas, chinchorros, lugares y favoritos para montar la próxima ruta con sazón.
Rutas, paradas y listas para que el próximo plan salga con sabor desde el arranque.
</p>
<div className="mt-5 grid grid-cols-2 gap-3 text-sm">
<div className="rounded-2xl border border-white/10 bg-white/5 p-3">
<div className="text-2xl font-black text-[#FDE68A]">{guideStats.routes}</div>
<div className="text-slate-300">rutas listas</div>
<div className="text-slate-300">rutas para salir</div>
</div>
<div className="rounded-2xl border border-white/10 bg-white/5 p-3">
<div className="text-2xl font-black text-[#A7F3D0]">{guideStats.chinchorros}</div>
<div className="text-slate-300">paradas</div>
<div className="text-slate-300">chinchorros recomendados</div>
</div>
</div>
</div>
@ -135,7 +135,7 @@ export default function PublicShell({ activeSection, children, floatingAction }:
<span className="mr-2">{item.emoji}</span>
{item.label}
</div>
<div className="text-xs text-slate-400">Dale una vuelta</div>
<div className="text-xs text-slate-400">Échale un ojo</div>
</div>
</Link>
);
@ -149,7 +149,7 @@ export default function PublicShell({ activeSection, children, floatingAction }:
className="flex flex-1 items-center justify-center gap-2 rounded-2xl border border-white/10 bg-white/5 px-3 py-3 text-sm font-semibold text-white transition hover:border-white/20 hover:bg-white/10"
>
<BaseIcon path={mdiLogin} size={18} />
Área privada
Iniciar sesión
</Link>
<button
type="button"
@ -177,7 +177,7 @@ export default function PublicShell({ activeSection, children, floatingAction }:
className="hidden items-center gap-2 rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold text-white transition hover:border-white/20 hover:bg-white/10 sm:inline-flex"
>
<BaseIcon path={mdiLogin} size={16} />
Área privada
Iniciar sesión
</Link>
<button
type="button"

View File

@ -24,7 +24,7 @@ export default function RoutePreview({ route, compact = false }: Props) {
<div className="flex items-start justify-between gap-3">
<div>
<div className="text-xs font-semibold uppercase tracking-[0.25em] text-white/80">
Vista rápida
De un vistazo
</div>
<div className="mt-1 text-lg font-black tracking-tight">{route.region}</div>
</div>
@ -50,8 +50,8 @@ export default function RoutePreview({ route, compact = false }: Props) {
</div>
<div className="mt-5 flex items-center justify-between text-xs text-white/90">
<span>{route.stops.length} paradas</span>
<span>{Math.round(route.estimatedMinutes / 60)}h aprox.</span>
<span>{route.stops.length} paradas clave</span>
<span>{Math.round(route.estimatedMinutes / 60)} h aprox.</span>
</div>
</div>
</div>

View File

@ -156,7 +156,7 @@ export const useChinchorreoStorage = () => {
if (!trimmedName) {
return {
ok: false,
message: 'Ponle un nombre a la lista para guardarla.',
message: 'Ponle un nombre a la lista para crearla.',
};
}
@ -179,7 +179,7 @@ export const useChinchorreoStorage = () => {
return {
ok: true,
message: `Lista “${trimmedName}creada y lista para usar.`,
message: `La lista “${trimmedName}quedó creada y activa.`,
list: createdList,
};
},

View File

@ -90,8 +90,8 @@ export default function EventsPage() {
setFeedback(
result.added
? `Evento guardado en “${activeList?.name || 'Mi chinchorreo'}”.`
: 'Ese evento ya estaba en la lista activa.',
? `Ese evento se guardó en “${activeList?.name || 'Mi chinchorreo'}”.`
: 'Ese evento ya lo tenías en la lista activa.',
);
};
@ -106,10 +106,10 @@ export default function EventsPage() {
<div className="max-w-3xl">
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">Eventos & Festivales</div>
<h1 className="mt-2 text-4xl font-black tracking-tight text-white">
Calendario sabroso entre comida, cultura y tradición
Festivales y planes para que no se te vaya ninguno
</h1>
<p className="mt-3 text-base leading-7 text-slate-300">
Aquí tienes un calendario mensual simplificado con contador regresivo y una lista de los próximos eventos más importantes del chinchorreo boricua.
Revisa qué viene por ahí, cuándo cae y cuál vale la pena apuntar para el próximo jangueo.
</p>
</div>
@ -117,7 +117,7 @@ export default function EventsPage() {
<input
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Buscar por festival, pueblo o lugar"
placeholder="Festival, pueblo o lugar..."
className="w-full rounded-2xl border border-white/10 bg-[#04111f]/50 px-4 py-3 text-white placeholder:text-slate-400 focus:border-[#DAA520] focus:outline-none focus:ring-0"
/>
</div>
@ -134,11 +134,11 @@ export default function EventsPage() {
<div className="rounded-[2rem] border border-white/10 bg-white/5 p-6 shadow-xl shadow-black/20">
<div className="flex items-center justify-between gap-3">
<div>
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">Mes destacado</div>
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">Mes en agenda</div>
<h2 className="mt-2 text-3xl font-black text-white">{monthLabel(calendarMonth)}</h2>
</div>
<div className="rounded-full border border-white/10 bg-white/5 px-3 py-2 text-sm font-semibold text-slate-200">
{filteredEvents.length} eventos visibles
{filteredEvents.length} eventos en agenda
</div>
</div>
@ -197,15 +197,15 @@ export default function EventsPage() {
<div className="space-y-4 p-5">
<div className="grid gap-3 md:grid-cols-3">
<div className="rounded-[1.4rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-300">
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Fecha</div>
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Cuándo</div>
<div className="mt-2 font-semibold text-white">{formatEventDate(event.nextDateIso)}</div>
</div>
<div className="rounded-[1.4rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-300">
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Lugar</div>
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Dónde</div>
<div className="mt-2 font-semibold text-white">{event.venue}</div>
</div>
<div className="rounded-[1.4rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-300">
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Cuenta regresiva</div>
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Falta</div>
<div className="mt-2 font-semibold text-[#FDE68A]">{getCountdownLabel(event.nextDateIso)}</div>
</div>
</div>
@ -225,7 +225,7 @@ export default function EventsPage() {
].join(' ')}
>
<BaseIcon path={mdiStarOutline} size={16} />
{saved ? 'Evento guardado' : 'Guardar evento'}
{saved ? 'Ya guardado' : 'Guardar'}
</button>
<div className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm text-slate-200">
<BaseIcon path={mdiCalendarStar} size={16} />
@ -241,9 +241,9 @@ export default function EventsPage() {
{!filteredEvents.length ? (
<section className="rounded-[2rem] border border-dashed border-white/15 bg-white/5 p-10 text-center shadow-xl shadow-black/20">
<h2 className="text-2xl font-black text-white">No salió ningún evento con esa búsqueda</h2>
<h2 className="text-2xl font-black text-white">No encontramos ningún evento con esa búsqueda</h2>
<p className="mt-3 text-sm leading-6 text-slate-300">
Prueba con otro pueblo o lugar, o limpia la búsqueda para ver qué viene por ahí.
Prueba con otro pueblo o limpia la búsqueda para ver los que vienen por ahí.
</p>
</section>
) : null}

View File

@ -56,7 +56,7 @@ const SectionHeader = ({
href={href}
className="inline-flex items-center gap-2 self-start rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold text-white transition hover:border-white/20 hover:bg-white/10"
>
Ver todo
Ver más
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
) : null}
@ -93,7 +93,7 @@ export default function HomePage() {
<PublicShell
activeSection="inicio"
floatingAction={{
label: 'Sorpréndeme con una ruta 🎲',
label: 'Dame una ruta 🎲',
icon: mdiDice5Outline,
onClick: handleRandomRoute,
}}
@ -115,11 +115,10 @@ export default function HomePage() {
¡Vamos a chinchorrear!
</div>
<h1 className="mt-5 text-4xl font-black tracking-tight text-white sm:text-5xl lg:text-6xl">
Tu guía interactiva para janguear Puerto Rico con sabor, ruta y corillo.
Tu próxima salida por Puerto Rico empieza aquí.
</h1>
<p className="mt-4 max-w-2xl text-base leading-7 text-slate-200 sm:text-lg">
Explora rutas auténticas, guarda tus paradas favoritas y descubre eventos, vistas y
chinchorros con una estética boricua vibrante y elegante.
Encuentra rutas, guarda paradas, mira eventos y descubre chinchorros para cuadrar el plan sin tanta vuelta.
</p>
<div className="relative mt-6 max-w-2xl">
@ -130,7 +129,7 @@ export default function HomePage() {
<input
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Buscar restaurante, ruta, pueblo o festival"
placeholder="Ruta, chinchorro, pueblo o festival..."
className="w-full border-0 bg-transparent text-base text-white placeholder:text-slate-400 focus:ring-0"
/>
<button
@ -171,23 +170,23 @@ export default function HomePage() {
className="inline-flex items-center gap-2 rounded-full bg-[#CE1126] px-5 py-3 text-sm font-bold text-white transition hover:bg-[#b90f23]"
>
<BaseIcon path={mdiMapMarkerPath} size={18} />
Explorar rutas
Ver rutas
</Link>
<Link
href="/login"
className="inline-flex items-center gap-2 rounded-full border border-white/15 bg-white/10 px-5 py-3 text-sm font-bold text-white transition hover:border-white/25 hover:bg-white/15"
>
<BaseIcon path={mdiLogin} size={18} />
Área privada
Iniciar sesión
</Link>
</div>
</div>
<div className="grid gap-4 sm:grid-cols-3 lg:grid-cols-1">
{[
{ label: 'Rutas curadas', value: guideStats.routes, accent: '#FDE68A' },
{ label: 'Chinchorros destacados', value: guideStats.chinchorros, accent: '#A7F3D0' },
{ label: 'Eventos cercanos', value: guideStats.events, accent: '#BFDBFE' },
{ label: 'Rutas bien armadas', value: guideStats.routes, accent: '#FDE68A' },
{ label: 'Chinchorros recomendados', value: guideStats.chinchorros, accent: '#A7F3D0' },
{ label: 'Eventos por venir', value: guideStats.events, accent: '#BFDBFE' },
].map((stat) => (
<div
key={stat.label}
@ -199,7 +198,7 @@ export default function HomePage() {
<div className="mt-3 text-4xl font-black tracking-tight" style={{ color: stat.accent }}>
{stat.value}
</div>
<div className="mt-2 text-sm text-slate-200">Listas para descubrir hoy mismo.</div>
<div className="mt-2 text-sm text-slate-200">Buenas para arrancar hoy mismo.</div>
</div>
))}
</div>
@ -285,7 +284,7 @@ export default function HomePage() {
href={`/restaurantes?search=${encodeURIComponent(stop.name)}`}
className="inline-flex items-center gap-2 text-sm font-semibold text-[#FDE68A]"
>
Ver en la guía
Abrir en la guía
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
</div>
@ -322,7 +321,7 @@ export default function HomePage() {
</div>
<div className="mt-4 inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-3 py-2 text-xs font-semibold text-slate-200">
<BaseIcon path={mdiWeatherPartlyCloudy} size={16} />
Ideal para ruta mixta de costa y montaña
Buen día para mezclar costa y montaña
</div>
</div>
@ -340,7 +339,7 @@ export default function HomePage() {
href="/tips"
className="mt-4 inline-flex items-center gap-2 text-sm font-semibold text-[#A7F3D0]"
>
Ver guía completa
Ver tips
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
</div>

View File

@ -53,45 +53,44 @@ export default function PlacesPage() {
setFeedback(
result.added
? `Lugar guardado en “${activeList?.name || 'Mi chinchorreo'}”.`
: 'Ese lugar ya estaba en la lista activa.',
? `Ese lugar se guardó en “${activeList?.name || 'Mi chinchorreo'}”.`
: 'Ese lugar ya lo tenías en la lista activa.',
);
};
return (
<>
<Head>
<title>Chinchorreo PR | Lugares de Interés</title>
<title>Chinchorreo PR | Lugares</title>
</Head>
<PublicShell activeSection="lugares">
<section className="rounded-[2rem] border border-white/10 bg-white/5 p-6 shadow-xl shadow-black/20 sm:p-8">
<div className="max-w-3xl">
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">Lugares de interés</div>
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">Lugares</div>
<h1 className="mt-2 text-4xl font-black tracking-tight text-white">
Playas, miradores, pueblos y cultura para completar la ruta
Playas, miradores y pueblos que le suman al plan
</h1>
<p className="mt-3 text-base leading-7 text-slate-300">
Usa estos lugares como pausas estratégicas entre paradas gastronómicas: fotos, vistas,
artesanías o una caminata corta para seguir con el plan.
Aquí encuentras paradas buenas para sacar fotos, coger aire o meterle una vista brutal antes de seguir.
</p>
</div>
<div className="mt-6 grid gap-4 rounded-[1.8rem] border border-white/10 bg-[#04111f]/50 p-4 md:grid-cols-[2fr_1fr]">
<label className="block">
<div className="mb-2 text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">
Buscar lugar
Busca un lugar
</div>
<input
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Loíza, playa, mirador, cultura..."
placeholder="Pueblo, playa, mirador o plan cultural..."
className="w-full rounded-2xl border border-white/10 bg-white/5 px-4 py-3 text-white placeholder:text-slate-400 focus:border-[#DAA520] focus:outline-none focus:ring-0"
/>
</label>
<label className="block">
<div className="mb-2 text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">
Categoría
Tipo de lugar
</div>
<select
value={selectedCategory}
@ -109,7 +108,7 @@ export default function PlacesPage() {
<div className="mt-4 flex flex-wrap items-center gap-3 text-sm text-slate-300">
<div className="rounded-full border border-white/10 bg-white/5 px-4 py-2">
{filteredPlaces.length} lugares disponibles
{filteredPlaces.length} paradas para explorar
</div>
{feedback ? (
<div className="inline-flex items-center gap-2 rounded-full border border-[#228B22]/30 bg-[#228B22]/10 px-4 py-2 text-[#A7F3D0]">
@ -122,9 +121,9 @@ export default function PlacesPage() {
{!filteredPlaces.length ? (
<section className="rounded-[2rem] border border-dashed border-white/15 bg-white/5 p-10 text-center shadow-xl shadow-black/20">
<h2 className="text-2xl font-black text-white">Con esos filtros no salió ningún lugar</h2>
<h2 className="text-2xl font-black text-white">No encontramos ningún lugar con esos filtros</h2>
<p className="mt-3 text-sm leading-6 text-slate-300">
Prueba otro pueblo, cambia la categoría o borra la búsqueda para seguir explorando.
Prueba otro pueblo, cambia el tipo de lugar o borra la búsqueda para seguir mirando.
</p>
</section>
) : null}
@ -152,11 +151,11 @@ export default function PlacesPage() {
<div className="space-y-4 p-5">
<p className="text-sm leading-6 text-slate-300">{place.description}</p>
<div className="rounded-[1.4rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-300">
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Mejor horario</div>
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Cuándo ir</div>
<div className="mt-2 font-semibold text-white">{place.bestTime}</div>
</div>
<div className="rounded-[1.4rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-300">
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Consejo local</div>
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Dato local</div>
<div className="mt-2 leading-6 text-white">{place.localTip}</div>
</div>
<div className="flex flex-wrap gap-3">
@ -167,7 +166,7 @@ export default function PlacesPage() {
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold text-white transition hover:border-white/20 hover:bg-white/10"
>
<BaseIcon path={mdiCompassOutline} size={16} />
Cómo llegar
Abrir en Maps
</a>
<button
type="button"
@ -180,7 +179,7 @@ export default function PlacesPage() {
].join(' ')}
>
<BaseIcon path={mdiStarOutline} size={16} />
{saved ? 'Lugar guardado' : 'Guardar lugar'}
{saved ? 'Ya guardado' : 'Guardar'}
</button>
</div>
<div className="inline-flex items-center gap-2 text-sm text-slate-300">

View File

@ -118,27 +118,27 @@ export default function MapPage() {
<div className="max-w-3xl">
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">Mapa interactivo</div>
<h1 className="mt-2 text-4xl font-black tracking-tight text-white">
Un mapa estilizado para descubrir paradas por categoría
Mira todo en mapa y arma la ruta a tu manera
</h1>
<p className="mt-3 text-base leading-7 text-slate-300">
Esta primera versión te deja alternar entre mapa y lista, filtrar categorías y trazar una mini ruta con los pins que selecciones.
Explora por mapa o por lista, filtra lo que quieres ver y marca las paradas que te llamen.
</p>
</div>
<div className="mt-6 grid gap-4 rounded-[1.8rem] border border-white/10 bg-[#04111f]/50 p-4 md:grid-cols-[2fr_1fr_1fr] lg:grid-cols-[2fr_1fr_1fr_1fr]">
<label className="block md:col-span-1 lg:col-span-2">
<div className="mb-2 text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">
Buscar pin
Busca una parada
</div>
<input
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Piñones, Loíza, Luquillo, cultura..."
placeholder="Pueblo, parada, chinchorro o plan cultural..."
className="w-full rounded-2xl border border-white/10 bg-white/5 px-4 py-3 text-white placeholder:text-slate-400 focus:border-[#DAA520] focus:outline-none focus:ring-0"
/>
</label>
<div className="flex flex-col gap-2">
<div className="text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">Categorías</div>
<div className="text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">Qué quieres ver</div>
<button
type="button"
onClick={() => setShowChinchorros((current) => !current)}
@ -165,7 +165,7 @@ export default function MapPage() {
</button>
</div>
<div className="flex flex-col gap-2">
<div className="text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">Vista</div>
<div className="text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">Cómo verlo</div>
{(['mapa', 'lista'] as MapViewMode[]).map((viewMode) => (
<button
key={viewMode}
@ -227,9 +227,9 @@ export default function MapPage() {
<div className="absolute bottom-6 left-6 rounded-[1.6rem] border border-white/10 bg-[#04111f]/70 p-4 text-sm text-slate-200 backdrop-blur">
<div className="inline-flex items-center gap-2 text-[#FDE68A]">
<BaseIcon path={mdiMapLegend} size={16} />
Selecciona un pin para ver detalle
Toca una parada para verla mejor
</div>
<div className="mt-2">Usa Agregar a la ruta para conectar varios puntos.</div>
<div className="mt-2">Si te gusta una, súmala con Sumar a la ruta.</div>
</div>
</div>
) : (
@ -263,7 +263,7 @@ export default function MapPage() {
: 'border-white/10 bg-white/5 text-white hover:border-white/20 hover:bg-white/10',
].join(' ')}
>
{inRoute ? 'Quitar de la ruta' : 'Agregar a la ruta'}
{inRoute ? 'Sacar de la ruta' : 'Sumar a la ruta'}
</button>
</article>
);
@ -297,7 +297,7 @@ export default function MapPage() {
href={selectedItem.href}
className="inline-flex items-center gap-2 rounded-full bg-white px-4 py-2 text-sm font-semibold text-[#04111f]"
>
Ver en la guía
Abrir en la guía
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
<a
@ -307,7 +307,7 @@ export default function MapPage() {
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold text-white transition hover:border-white/20 hover:bg-white/10"
>
<BaseIcon path={mdiCompassOutline} size={16} />
Google Maps
Abrir en Maps
</a>
<button
type="button"
@ -320,8 +320,8 @@ export default function MapPage() {
].join(' ')}
>
{routeSelection.includes(selectedItem.id)
? 'Quitar de la ruta'
: 'Agregar a la ruta'}
? 'Sacar de la ruta'
: 'Sumar a la ruta'}
</button>
</div>
</div>
@ -350,14 +350,14 @@ export default function MapPage() {
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-3 py-2 text-xs font-semibold text-slate-200"
>
<BaseIcon path={mdiCloseCircleOutline} size={14} />
Quitar
Sacar
</button>
</div>
))}
</div>
) : (
<div className="mt-5 rounded-[1.6rem] border border-dashed border-white/10 bg-[#04111f]/40 p-5 text-sm leading-6 text-slate-300">
Marca varias paradas para armar una mini ruta. Con dos o más ya puedes abrirla.
Suma varias paradas y aquí se te arma la mini ruta. Con dos o más ya la puedes abrir.
</div>
)}
@ -369,7 +369,7 @@ export default function MapPage() {
className="mt-5 inline-flex items-center gap-2 rounded-full bg-white px-5 py-3 text-sm font-bold text-[#04111f]"
>
<BaseIcon path={mdiMapSearchOutline} size={16} />
Abrir ruta
Abrir en Maps
</a>
) : null}
</div>
@ -378,9 +378,9 @@ export default function MapPage() {
{!visibleItems.length ? (
<section className="rounded-[2rem] border border-dashed border-white/15 bg-white/5 p-10 text-center shadow-xl shadow-black/20">
<h2 className="text-2xl font-black text-white">Con esos filtros no se ve ninguna parada en el mapa</h2>
<h2 className="text-2xl font-black text-white">No encontramos paradas con esos filtros</h2>
<p className="mt-3 text-sm leading-6 text-slate-300">
Vuelve a activar chinchorros o lugares, o limpia la búsqueda para verlo completo otra vez.
Activa otra vez chinchorros o lugares, o limpia la búsqueda para verlo completo.
</p>
</section>
) : null}

View File

@ -21,7 +21,7 @@ import LayoutGuest from '../layouts/Guest';
const categoryLabels: Record<FavoriteCategory, string> = {
route: 'Rutas',
chinchorro: 'Restaurantes',
chinchorro: 'Chinchorros',
place: 'Lugares',
event: 'Eventos',
};
@ -73,7 +73,7 @@ export default function FavoritesPage() {
const shareList = () => {
if (!activeFavorites.length) {
setFeedback('Agrega al menos una ruta o chinchorro antes de compartir la lista.');
setFeedback('Guarda aunque sea una parada antes de compartir esta lista.');
return;
}
@ -91,52 +91,51 @@ export default function FavoritesPage() {
const handleRemoveFavorite = (category: FavoriteCategory, itemSlug: string) => {
removeFavorite(category, itemSlug, activeListId);
setFeedback('Se quitó de la lista activa.');
setFeedback('Lo saqué de esta lista.');
};
const handleRemoveList = () => {
const removed = removeList(activeListId);
setFeedback(
removed
? 'La lista personalizada fue eliminada.'
: 'La lista principal “Mi chinchorreo” no se puede eliminar.',
? 'Lista borrada.'
: '“Mi chinchorreo” es la lista principal y no se puede borrar.',
);
};
const handleClearList = () => {
clearListFavorites(activeListId);
setFeedback('Se vació la lista activa, pero la lista sigue creada.');
setFeedback('La lista quedó vacía, pero sigue ahí.');
};
return (
<>
<Head>
<title>Chinchorreo PR | Mis Favoritos</title>
<title>Chinchorreo PR | Favoritos</title>
</Head>
<PublicShell activeSection="favoritos">
<section className="grid gap-6 xl:grid-cols-[1fr_1fr]">
<div className="rounded-[2rem] border border-white/10 bg-white/5 p-6 shadow-xl shadow-black/20 sm:p-8">
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">Mis Favoritos</div>
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">Favoritos</div>
<h1 className="mt-2 text-4xl font-black tracking-tight text-white">
Crea listas y guarda tus próximos jangueos
Guarda ideas para el próximo chinchorreo
</h1>
<p className="mt-3 text-base leading-7 text-slate-300">
Tus favoritos se guardan en este dispositivo: puedes crear listas,
elegir una lista activa y compartirla por WhatsApp.
Arma listas por plan, deja una activa y comparte por WhatsApp lo que ya vas cuadrando.
</p>
<div className="mt-6 grid gap-4 sm:grid-cols-3">
<div className="rounded-[1.7rem] border border-white/10 bg-[#04111f]/60 p-4">
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Listas</div>
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Tus listas</div>
<div className="mt-2 text-3xl font-black text-white">{lists.length}</div>
</div>
<div className="rounded-[1.7rem] border border-white/10 bg-[#04111f]/60 p-4">
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Activa</div>
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Lista activa</div>
<div className="mt-2 text-xl font-black text-[#FDE68A]">{activeList?.name}</div>
</div>
<div className="rounded-[1.7rem] border border-white/10 bg-[#04111f]/60 p-4">
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Guardados</div>
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">En esta lista</div>
<div className="mt-2 text-3xl font-black text-white">{activeFavorites.length}</div>
</div>
</div>
@ -185,7 +184,7 @@ export default function FavoritesPage() {
type="submit"
className="inline-flex items-center gap-2 rounded-full bg-white px-5 py-3 text-sm font-bold text-[#04111f]"
>
Crear lista
Crear esta lista
<BaseIcon path={mdiChevronRight} size={16} />
</button>
</div>
@ -205,14 +204,14 @@ export default function FavoritesPage() {
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold text-white transition hover:border-white/20 hover:bg-white/10"
>
<BaseIcon path={mdiShareVariantOutline} size={16} />
Compartir lista
Compartir por WhatsApp
</button>
<button
type="button"
onClick={handleClearList}
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-transparent px-4 py-2 text-sm font-semibold text-slate-200 transition hover:border-white/20 hover:bg-white/5"
>
Vaciar esta lista
Dejarla vacía
</button>
{activeListId !== DEFAULT_PUBLIC_LIST_ID ? (
<button
@ -220,7 +219,7 @@ export default function FavoritesPage() {
onClick={handleRemoveList}
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-transparent px-4 py-2 text-sm font-semibold text-slate-200 transition hover:border-white/20 hover:bg-white/5"
>
Eliminar lista
Borrar lista
</button>
) : null}
</div>
@ -242,12 +241,12 @@ export default function FavoritesPage() {
].join(' ')}
>
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">
{isActive ? 'Lista activa' : 'Usar esta lista'}
{isActive ? 'La que estás usando' : 'Usar esta'}
</div>
<h3 className="mt-2 text-2xl font-black text-white">{list.name}</h3>
<p className="mt-2 text-sm leading-6 text-slate-300">{list.description}</p>
<div className="mt-4 text-sm text-slate-400">
{(favoritesByList[list.id] || []).length} guardados
{(favoritesByList[list.id] || []).length} guardados aquí
</div>
</button>
);
@ -268,7 +267,7 @@ export default function FavoritesPage() {
<div className={`text-xs font-bold uppercase tracking-[0.35em] ${categoryAccents[category]}`}>
{categoryLabels[category]}
</div>
<h2 className="mt-2 text-2xl font-black text-white">{items.length} guardados</h2>
<h2 className="mt-2 text-2xl font-black text-white">{items.length} en esta categoría</h2>
</div>
<div className="rounded-full border border-white/10 bg-white/5 px-3 py-2 text-sm font-semibold text-slate-200">
{categoryLabels[category]}
@ -296,7 +295,7 @@ export default function FavoritesPage() {
href={item.itemHref}
className="inline-flex items-center gap-2 rounded-full bg-white px-4 py-2 text-sm font-semibold text-[#04111f]"
>
Ver en la guía
Abrir en la guía
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
<button
@ -305,7 +304,7 @@ export default function FavoritesPage() {
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-transparent px-4 py-2 text-sm font-semibold text-slate-200 transition hover:border-white/20 hover:bg-white/5"
>
<BaseIcon path={mdiCloseCircleOutline} size={16} />
Quitar
Sacar
</button>
</div>
</div>
@ -313,7 +312,7 @@ export default function FavoritesPage() {
</div>
) : (
<div className="mt-5 rounded-[1.6rem] border border-dashed border-white/10 bg-[#04111f]/40 p-6 text-sm leading-6 text-slate-300">
Aquí todavía no has guardado {categoryLabels[category].toLowerCase()} en esta lista.
Todavía no has guardado {categoryLabels[category].toLowerCase()} en esta lista.
</div>
)}
</article>
@ -324,7 +323,7 @@ export default function FavoritesPage() {
{!activeFavorites.length ? (
<section className="rounded-[2rem] border border-dashed border-white/15 bg-white/5 p-10 text-center shadow-xl shadow-black/20">
<BaseIcon path={mdiStarOutline} size={42} className="mx-auto text-[#FDE68A]" />
<h2 className="mt-4 text-3xl font-black text-white">Esta lista está vacía por ahora</h2>
<h2 className="mt-4 text-3xl font-black text-white">Todavía no hay nada en esta lista</h2>
<p className="mt-3 text-sm leading-6 text-slate-300">
Guarda una ruta, un chinchorro o un lugar desde la guía y aquí se te irá armando el plan.
</p>
@ -333,13 +332,13 @@ export default function FavoritesPage() {
href="/rutas"
className="rounded-full bg-white px-5 py-3 text-sm font-bold text-[#04111f]"
>
Explorar rutas
Ir a rutas
</Link>
<Link
href="/restaurantes"
className="rounded-full border border-white/10 bg-white/5 px-5 py-3 text-sm font-bold text-white"
>
Ver chinchorros
Ir a chinchorros
</Link>
</div>
</section>

View File

@ -90,15 +90,15 @@ export default function RestaurantsPage() {
setFeedback(
result.added
? `Chinchorro guardado en “${activeList?.name || 'Mi chinchorreo'}”.`
: 'Ese chinchorro ya estaba en la lista activa.',
? `Ese chinchorro se guardó en “${activeList?.name || 'Mi chinchorreo'}”.`
: 'Ese chinchorro ya lo tenías en la lista activa.',
);
};
return (
<>
<Head>
<title>Chinchorreo PR | Restaurantes & Chinchorros</title>
<title>Chinchorreo PR | Chinchorros</title>
</Head>
<PublicShell activeSection="restaurantes">
@ -106,14 +106,13 @@ export default function RestaurantsPage() {
<div className="flex flex-col gap-6 lg:flex-row lg:items-end lg:justify-between">
<div className="max-w-3xl">
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">
Restaurantes & Chinchorros
Chinchorros
</div>
<h1 className="mt-2 text-4xl font-black tracking-tight text-white">
Filtra por región, ambiente y antojo
Encuentra un chinchorro según el antojo y el ambiente
</h1>
<p className="mt-3 text-base leading-7 text-slate-300">
Desde Piñones hasta La Parguera, aquí tienes una lista buscable con especialidades,
redes, mapas y favoritos guardados localmente.
Desde Piñones hasta La Parguera, aquí buscas por zona, ambiente o antojo y guardas los chinchorros que quieres repetir.
</p>
</div>
<button
@ -134,25 +133,25 @@ export default function RestaurantsPage() {
<div className="mt-6 grid gap-4 rounded-[1.8rem] border border-white/10 bg-[#04111f]/50 p-4 md:grid-cols-2 xl:grid-cols-5">
<label className="block xl:col-span-2">
<div className="mb-2 text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">
Buscar
Busca un chinchorro
</div>
<input
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Piñones, lechonera, longaniza, Luquillo..."
placeholder="Piñones, lechonera, fritura o Luquillo..."
className="w-full rounded-2xl border border-white/10 bg-white/5 px-4 py-3 text-white placeholder:text-slate-400 focus:border-[#DAA520] focus:outline-none focus:ring-0"
/>
</label>
{[
{
title: 'Región',
title: 'Zona',
value: selectedRegion,
options: ['Todas', ...regionOptions],
onChange: setSelectedRegion,
},
{
title: 'Tipo',
title: 'Tipo de chinchorro',
value: selectedType,
options: ['Todas', ...typeOptions],
onChange: setSelectedType,
@ -164,7 +163,7 @@ export default function RestaurantsPage() {
onChange: setSelectedVibe,
},
{
title: 'Precio',
title: 'Presupuesto',
value: selectedPrice,
options: ['Todas', ...priceOptions],
onChange: setSelectedPrice,
@ -200,10 +199,10 @@ export default function RestaurantsPage() {
: 'border-white/10 bg-white/5 text-white hover:border-white/20 hover:bg-white/10',
].join(' ')}
>
Abierto ahora {openNowOnly ? '✓' : ''}
Solo abiertos ahora {openNowOnly ? '✓' : ''}
</button>
<div className="rounded-full border border-white/10 bg-white/5 px-4 py-2">
{filteredChinchorros.length} chinchorros encontrados
{filteredChinchorros.length} chinchorros para este plan
</div>
{feedback ? (
<div className="inline-flex items-center gap-2 rounded-full border border-[#228B22]/30 bg-[#228B22]/10 px-4 py-2 text-[#A7F3D0]">
@ -261,26 +260,26 @@ export default function RestaurantsPage() {
: 'border-white/10 bg-white/5 text-slate-300',
].join(' ')}
>
{chinchorro.openNow ? 'Abierto ahora' : 'Abre luego'}
{chinchorro.openNow ? 'Abierto ahora' : 'Cerrado ahora'}
</div>
</div>
<div className="grid gap-3 sm:grid-cols-2">
<div className="rounded-[1.4rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-300">
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Dirección</div>
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Dónde queda</div>
<div className="mt-2 flex items-start gap-2 text-white">
<BaseIcon path={mdiMapMarker} size={16} className="mt-0.5" />
<span>{chinchorro.address}</span>
</div>
</div>
<div className="rounded-[1.4rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-300">
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Horario</div>
<div className="text-xs uppercase tracking-[0.2em] text-slate-500">Cuándo ir</div>
<div className="mt-2 text-white">{chinchorro.hours}</div>
</div>
</div>
<div>
<div className="text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">Especialidades</div>
<div className="text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">Qué pedir</div>
<div className="mt-3 flex flex-wrap gap-2">
{chinchorro.specialties.map((specialty) => (
<span
@ -294,7 +293,7 @@ export default function RestaurantsPage() {
</div>
<div>
<div className="text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">Galería de platos</div>
<div className="text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">Se antoja pedir</div>
<div className="mt-3 grid gap-3 sm:grid-cols-3">
{chinchorro.dishGallery.map((dish) => (
<div
@ -353,7 +352,7 @@ export default function RestaurantsPage() {
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-4 py-2 text-sm font-semibold text-white transition hover:border-white/20 hover:bg-white/10"
>
<BaseIcon path={mdiOpenInNew} size={16} />
Google Maps
Abrir en Maps
</a>
<button
type="button"
@ -373,14 +372,14 @@ export default function RestaurantsPage() {
].join(' ')}
>
<BaseIcon path={mdiStarOutline} size={16} />
{saved ? 'Chinchorro guardado' : 'Guardar chinchorro'}
{saved ? 'Ya guardado' : 'Guardar'}
</button>
{chinchorro.routeSlug ? (
<Link
href={`/rutas/${chinchorro.routeSlug}`}
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-transparent px-4 py-2 text-sm font-semibold text-slate-200 transition hover:border-white/20 hover:bg-white/5"
>
Ver ruta
Abrir ruta
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
) : null}
@ -393,9 +392,9 @@ export default function RestaurantsPage() {
{!filteredChinchorros.length ? (
<section className="rounded-[2rem] border border-dashed border-white/15 bg-white/5 p-10 text-center shadow-xl shadow-black/20">
<h2 className="text-2xl font-black text-white">Con esos filtros no salió ningún chinchorro</h2>
<h2 className="text-2xl font-black text-white">No encontramos ningún chinchorro con esos filtros</h2>
<p className="mt-3 text-sm leading-6 text-slate-300">
Prueba otro pueblo, quita Abierto ahora o cambia la región para ver más opciones.
Prueba otra zona, cambia el presupuesto o quita Solo abiertos ahora.
</p>
</section>
) : null}

View File

@ -61,7 +61,7 @@ export default function RouteDetailPage() {
href="/rutas"
className="mt-5 inline-flex items-center gap-2 rounded-full bg-white px-5 py-3 text-sm font-bold text-[#04111f]"
>
Volver a rutas
Regresar a rutas
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
</section>
@ -85,14 +85,14 @@ export default function RouteDetailPage() {
setFeedback(
result.added
? `Ruta guardada en “${activeList?.name || 'Mi chinchorreo'}”.`
: 'Esta ruta ya está guardada en tu lista activa.',
? `Esa ruta se guardó en “${activeList?.name || 'Mi chinchorreo'}”.`
: 'Esa ruta ya estaba en tu lista activa.',
);
};
const handleToggleStop = (stopId: string) => {
const result = toggleRouteStop(route.slug, stopId);
setFeedback(result.completed ? 'Parada marcada como completada ✅' : 'Parada marcada como pendiente.');
setFeedback(result.completed ? 'Parada marcada como hecha ✅' : 'La parada volvió a quedar pendiente.');
};
return (
@ -114,7 +114,7 @@ export default function RouteDetailPage() {
<div className="relative grid gap-8 lg:grid-cols-[1.05fr_0.95fr] lg:items-end">
<div>
<Link href="/rutas" className="inline-flex items-center gap-2 text-sm font-semibold text-slate-200">
Volver a rutas
Regresar a rutas
</Link>
<div className="mt-4 inline-flex items-center gap-2 rounded-full border border-white/15 bg-white/10 px-4 py-2 text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">
{route.emoji} {route.region}
@ -143,7 +143,7 @@ export default function RouteDetailPage() {
className="inline-flex items-center gap-2 rounded-full bg-white px-5 py-3 text-sm font-bold text-[#04111f] transition hover:bg-slate-100"
>
<BaseIcon path={mdiCompassOutline} size={16} />
Abrir navegación
Abrir en Maps
</a>
<button
type="button"
@ -156,7 +156,7 @@ export default function RouteDetailPage() {
].join(' ')}
>
<BaseIcon path={mdiStarOutline} size={16} />
{saved ? 'Ruta guardada' : 'Guardar ruta'}
{saved ? 'Ya guardada' : 'Guardar'}
</button>
<button
type="button"
@ -164,7 +164,7 @@ export default function RouteDetailPage() {
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/10 px-5 py-3 text-sm font-bold text-white transition hover:border-white/20 hover:bg-white/15"
>
<BaseIcon path={mdiShareVariantOutline} size={16} />
Compartir ruta
Compartir
</button>
</div>
</div>
@ -186,9 +186,9 @@ export default function RouteDetailPage() {
</p>
</div>
<div className="rounded-[1.5rem] border border-white/10 bg-[#04111f]/60 px-4 py-3 text-sm text-slate-200">
<div className="font-semibold text-white">{progress}% completado</div>
<div className="font-semibold text-white">Llevas {progress}%</div>
<div className="mt-1 text-slate-400">
{completedStops.length} de {route.stops.length} paradas hechas
{completedStops.length} de {route.stops.length} ya hechas
</div>
</div>
</div>
@ -229,21 +229,21 @@ export default function RouteDetailPage() {
</div>
<div className="flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-3 py-2 text-sm font-semibold text-slate-200">
<BaseIcon path={mdiCheckCircleOutline} size={16} />
{completed ? 'Completada' : 'Marcar parada'}
{completed ? 'Ya está hecha' : 'Marcar parada'}
</div>
</div>
<div className="mt-5 grid gap-3 md:grid-cols-3">
<div className="rounded-[1.4rem] border border-white/10 bg-white/5 p-4">
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Especialidad</div>
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Prueba esto</div>
<div className="mt-2 text-sm font-semibold text-white">{stop.specialty}</div>
</div>
<div className="rounded-[1.4rem] border border-white/10 bg-white/5 p-4">
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Horario aprox.</div>
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Mejor momento</div>
<div className="mt-2 text-sm font-semibold text-white">{stop.hours}</div>
</div>
<div className="rounded-[1.4rem] border border-white/10 bg-white/5 p-4">
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Quédate</div>
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Quédate un rato</div>
<div className="mt-2 text-sm font-semibold text-white">{stop.recommendedStay}</div>
</div>
</div>
@ -256,23 +256,23 @@ export default function RouteDetailPage() {
<div className="space-y-6">
<div className="rounded-[2rem] border border-white/10 bg-white/5 p-6 shadow-xl shadow-black/20">
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#A7F3D0]">
Tu ritmo ideal
Hazla con calma
</div>
<div className="mt-3 flex items-center gap-3 text-white">
<BaseIcon path={mdiClockOutline} size={18} />
<div>
<div className="text-xl font-black">{route.estimatedMinutes} minutos estimados</div>
<div className="text-xl font-black">Más o menos {route.estimatedMinutes} min</div>
<div className="text-sm text-slate-300">Planifica entre 3 y 5 horas para disfrutarla completa.</div>
</div>
</div>
<div className="mt-5 rounded-[1.5rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm leading-6 text-slate-300">
{feedback || `Tu lista activa ahora mismo es${activeList?.name || 'Mi chinchorreo'}”.`}
{feedback || `Ahora mismo estás guardando en${activeList?.name || 'Mi chinchorreo'}”.`}
</div>
<Link
href="/mis-favoritos"
className="mt-5 inline-flex items-center gap-2 text-sm font-semibold text-[#FDE68A]"
>
Abrir favoritos
Ir a favoritos
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
</div>

View File

@ -86,8 +86,8 @@ export default function RoutesPage() {
setFeedback(
result.added
? `Ruta guardada en “${activeList?.name || 'Mi chinchorreo'}”.`
: 'Esta ruta ya estaba guardada en tu lista activa.',
? `Esa ruta se guardó en “${activeList?.name || 'Mi chinchorreo'}”.`
: 'Esa ruta ya estaba en tu lista activa.',
);
};
@ -100,7 +100,7 @@ export default function RoutesPage() {
<PublicShell
activeSection="rutas"
floatingAction={{
label: 'Sorpréndeme con otra ruta',
label: 'Dame otra ruta',
icon: mdiDice5Outline,
onClick: handleRandomRoute,
}}
@ -110,18 +110,17 @@ export default function RoutesPage() {
<div className="max-w-3xl">
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">Rutas</div>
<h1 className="mt-2 text-4xl font-black tracking-tight text-white">
Explora la isla parada por parada
Rutas para irte de parada en parada
</h1>
<p className="mt-3 text-base leading-7 text-slate-300">
Aquí puedes descubrir rutas populares, ver sus paradas en orden,
iniciar navegación y guardarlas en una lista personalizada.
Descubre recorridos ya armados, mira cada parada en orden y guarda los que mejor van con tu plan.
</p>
</div>
<div className="rounded-[1.75rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-200">
<div className="font-semibold text-white">Lista activa</div>
<div className="font-semibold text-white">Tu lista activa</div>
<div className="mt-1 text-[#FDE68A]">{activeList?.name || 'Mi chinchorreo'}</div>
<Link href="/mis-favoritos" className="mt-3 inline-flex items-center gap-2 text-sm font-semibold text-[#A7F3D0]">
Abrir favoritos
Ir a favoritos
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
</div>
@ -130,30 +129,30 @@ export default function RoutesPage() {
<div className="mt-6 grid gap-4 rounded-[1.8rem] border border-white/10 bg-[#04111f]/50 p-4 md:grid-cols-[2fr_1fr_1fr] lg:grid-cols-[2fr_1fr_1fr_1fr]">
<label className="block">
<div className="mb-2 text-xs font-semibold uppercase tracking-[0.25em] text-slate-400">
Buscar ruta
Busca una ruta
</div>
<input
value={searchValue}
onChange={(event) => setSearchValue(event.target.value)}
placeholder="Arecibo, montaña, mariscos, Guavate..."
placeholder="Arecibo, Guavate, mariscos o montaña..."
className="w-full rounded-2xl border border-white/10 bg-white/5 px-4 py-3 text-white placeholder:text-slate-400 focus:border-[#DAA520] focus:outline-none focus:ring-0"
/>
</label>
{[{
title: 'Región',
title: 'Zona',
value: selectedRegion,
options: regionFilters,
onChange: setSelectedRegion,
},
{
title: 'Dificultad',
title: 'Ritmo',
value: selectedDifficulty,
options: difficultyFilters,
onChange: setSelectedDifficulty,
},
{
title: 'Etiqueta',
title: 'Plan',
value: selectedTag,
options: tagFilters,
onChange: setSelectedTag,
@ -180,7 +179,7 @@ export default function RoutesPage() {
<div className="mt-4 flex flex-wrap items-center gap-3 text-sm text-slate-300">
<div className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-3 py-2">
<BaseIcon path={mdiFilterVariant} size={16} />
{filteredRoutes.length} rutas que van con tu plan
{filteredRoutes.length} rutas para este plan
</div>
{feedback ? (
<div className="inline-flex items-center gap-2 rounded-full border border-[#228B22]/30 bg-[#228B22]/10 px-3 py-2 text-[#A7F3D0]">
@ -215,7 +214,7 @@ export default function RoutesPage() {
<div className="font-semibold text-white">{route.bestFor}</div>
<div className="mt-2 flex items-center gap-2 text-slate-300">
<BaseIcon path={mdiClockOutline} size={16} />
{route.estimatedMinutes} min estimados
Aprox. {route.estimatedMinutes} min
</div>
</div>
</div>
@ -233,15 +232,15 @@ export default function RoutesPage() {
<div className="mt-6 grid gap-3 md:grid-cols-3">
<div className="rounded-[1.5rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-200">
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Paradas</div>
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Paradas clave</div>
<div className="mt-2 text-2xl font-black text-white">{route.stops.length}</div>
</div>
<div className="rounded-[1.5rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-200">
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Dificultad</div>
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Ritmo</div>
<div className="mt-2 text-xl font-black text-white">{route.difficulty}</div>
</div>
<div className="rounded-[1.5rem] border border-white/10 bg-[#04111f]/60 p-4 text-sm text-slate-200">
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Ideal para</div>
<div className="text-xs uppercase tracking-[0.25em] text-slate-400">Buen plan para</div>
<div className="mt-2 text-sm font-semibold text-white">{route.bestFor}</div>
</div>
</div>
@ -251,7 +250,7 @@ export default function RoutesPage() {
href={`/rutas/${route.slug}`}
className="inline-flex items-center gap-2 rounded-full bg-white px-5 py-3 text-sm font-bold text-[#04111f] transition hover:bg-slate-100"
>
Ver ruta
Abrir ruta
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
<a
@ -261,7 +260,7 @@ export default function RoutesPage() {
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-white/5 px-5 py-3 text-sm font-bold text-white transition hover:border-white/20 hover:bg-white/10"
>
<BaseIcon path={mdiCompassOutline} size={16} />
Navegar
Abrir en Maps
</a>
<button
type="button"
@ -274,7 +273,7 @@ export default function RoutesPage() {
].join(' ')}
>
<BaseIcon path={mdiStarOutline} size={16} />
{saved ? 'Ruta guardada' : 'Guardar ruta'}
{saved ? 'Ya guardada' : 'Guardar'}
</button>
<button
type="button"
@ -283,7 +282,7 @@ export default function RoutesPage() {
}
className="inline-flex items-center gap-2 rounded-full border border-white/10 bg-transparent px-5 py-3 text-sm font-bold text-slate-200 transition hover:border-white/20 hover:bg-white/5"
>
Compartir ruta
Compartir
</button>
</div>
</div>
@ -294,9 +293,9 @@ export default function RoutesPage() {
{!filteredRoutes.length ? (
<section className="rounded-[2rem] border border-dashed border-white/15 bg-white/5 p-10 text-center shadow-xl shadow-black/20">
<h2 className="text-2xl font-black text-white">Con esos filtros no salió ninguna ruta</h2>
<h2 className="text-2xl font-black text-white">No encontramos ninguna ruta con esos filtros</h2>
<p className="mt-3 text-sm leading-6 text-slate-300">
Quita una etiqueta, cambia la dificultad o dale a Sorpréndeme para que aparezca otra opción.
Prueba otra zona o ritmo, o dale a Dame otra ruta para ver una distinta.
</p>
<div className="mt-5 flex flex-wrap items-center justify-center gap-3">
<button
@ -309,14 +308,14 @@ export default function RoutesPage() {
}}
className="rounded-full bg-white px-5 py-3 text-sm font-bold text-[#04111f]"
>
Limpiar filtros
Quitar filtros
</button>
<button
type="button"
onClick={handleRandomRoute}
className="rounded-full border border-white/10 bg-white/5 px-5 py-3 text-sm font-bold text-white"
>
Sorpréndeme
Dame otra ruta
</button>
</div>
</section>

View File

@ -28,20 +28,20 @@ export default function TipsPage() {
return (
<>
<Head>
<title>Chinchorreo PR | Tips & Guía del Viajero</title>
<title>Chinchorreo PR | Tips</title>
</Head>
<PublicShell activeSection="tips">
<section className="grid gap-6 xl:grid-cols-[1.05fr_0.95fr]">
<div className="rounded-[2rem] border border-white/10 bg-white/5 p-6 shadow-xl shadow-black/20 sm:p-8">
<div className="text-xs font-bold uppercase tracking-[0.35em] text-[#FDE68A]">
Tips & Guía del viajero
Tips
</div>
<h1 className="mt-2 text-4xl font-black tracking-tight text-white">
Consejos prácticos para chinchorrear con calma y responsabilidad
Consejos para salir a chinchorrear con calma y buen juicio
</h1>
<p className="mt-3 max-w-2xl text-base leading-7 text-slate-300">
Una guía educativa para salir mejor preparado, comer mejor y respetar cada lugar que visitas.
Una guía sencilla para comer mejor, moverte con tiempo y cuidar cada parada que visites.
</p>
<div className="mt-6 rounded-[1.9rem] border border-[#DAA520]/20 bg-gradient-to-br from-[#DAA520]/10 via-white/5 to-transparent p-6">
@ -58,7 +58,7 @@ export default function TipsPage() {
onClick={() => setTipIndex((current) => current + 1)}
className="mt-5 inline-flex items-center gap-2 rounded-full bg-white px-5 py-3 text-sm font-bold text-[#04111f]"
>
Dame otro tip
Quiero otro tip
<BaseIcon path={mdiChevronRight} size={16} />
</button>
</div>
@ -81,7 +81,7 @@ export default function TipsPage() {
href="/rutas"
className="mt-6 inline-flex items-center gap-2 text-sm font-semibold text-[#FDE68A]"
>
Ver rutas y poner estos tips en práctica
Ir a rutas y ponerlos en práctica
<BaseIcon path={mdiChevronRight} size={16} />
</Link>
</div>