gate +18 con cookie de 1 dia (web + links page)

This commit is contained in:
Renato
2026-08-04 17:26:33 +08:00
parent 569245b440
commit 1825dfae4e
2 changed files with 68 additions and 0 deletions
+3
View File
@@ -1,11 +1,14 @@
import Link from "next/link"
import { Image, Search } from "lucide-react"
import { SITE_NAME, SITE_TAGLINE, SITE_LINKS } from "@/lib/site"
import { AgeGate } from "@/components/age-gate"
// Header del sitio público: búsqueda pública (SQLite) + logo.
export default function PublicLayout({ children }: { children: React.ReactNode }) {
return (
<>
{/* Gate +18 con persistencia de 1 día */}
<AgeGate />
<header className="sticky top-0 z-40 border-b border-[var(--border)] bg-[var(--background)]/85 backdrop-blur-md">
<div className="mx-auto flex h-14 max-w-5xl items-center justify-between px-3 sm:px-4">
<Link href="/" className="flex items-center gap-2.5">
+65
View File
@@ -0,0 +1,65 @@
"use client"
import { useEffect, useState } from "react"
const COOKIE_NAME = "ws_age_ok"
const COOKIE_DAYS = 1
// Gate de contenidos +18: se muestra hasta que el usuario confirma ser mayor.
// Persistencia: cookie de 1 día. Si dice ser menor -> Google.
export function AgeGate() {
const [show, setShow] = useState(false)
useEffect(() => {
const ok = document.cookie
.split(";")
.some((c) => c.trim().startsWith(`${COOKIE_NAME}=`))
setShow(!ok)
}, [])
const confirmAdult = () => {
const d = new Date()
d.setTime(d.getTime() + COOKIE_DAYS * 24 * 60 * 60 * 1000)
document.cookie = `${COOKIE_NAME}=1; expires=${d.toUTCString()}; path=/; max-age=${COOKIE_DAYS * 24 * 60 * 60}`
setShow(false)
}
const deny = () => {
window.location.href = "https://www.google.com/"
}
if (!show) return null
return (
<div className="fixed inset-0 z-[9999] flex items-center justify-center p-6 text-center">
{/* fondo */}
<div className="absolute inset-0 bg-[var(--background)]"
style={{ background: "radial-gradient(ellipse at top, #1a1a20 0%, rgba(9,9,11,0.4) 45%, var(--background) 100%), var(--background)" }} />
<div className="relative w-full max-w-sm flex flex-col items-center gap-5 rounded-3xl border border-[var(--border)] bg-[var(--surface)]/90 p-8 backdrop-blur-lg shadow-2xl animate-fade-up">
<div className="flex h-16 w-16 items-center justify-center rounded-full border-2 border-[var(--error)] text-2xl font-extrabold text-[var(--error)] shadow-[0_0_35px_rgba(239,68,68,0.3)]">
18+
</div>
<div className="text-center">
<h2 className="text-xl font-bold tracking-tight">Contenido para adultos</h2>
<p className="mt-2 text-xs text-[var(--muted)] leading-relaxed">
Este sitio contiene mangas con contenido explícito para mayores de 18 años.
</p>
</div>
<div className="flex w-full flex-col gap-2.5">
<button
onClick={confirmAdult}
className="btn-primary w-full py-3 text-sm"
>
Soy mayor de 18 años
</button>
<button
onClick={deny}
className="w-full rounded-[0.5rem] border border-[var(--border)] bg-transparent py-3 text-sm text-[var(--muted)] transition-colors hover:text-[var(--error)] hover:border-[var(--error)] hover:bg-[var(--error-subtle)]"
>
Soy menor de edad
</button>
</div>
</div>
</div>
)
}