web-next: «Personalizar» abre panel granular de cookies (uw-cookie-details)
El botón Personalizar del banner ahora despliega un panel con checkboxes por
categoría (Necesarias fija+desactivada, Analíticas, Marketing) y «Guardar
preferencias», tal como el markup del usuario. Al guardar, escribe la cookie
uw_cookie_consent con la selección granular y sincroniza con Zaraz. Categorías
alineadas a las del panel (Necesarias/Analíticas/Marketing); ConsentStatus y
acceptAll/rejectAll usan las mismas. Estilos del panel en globals.css.
Verificado: Personalizar abre el panel, marcar Analíticas + Guardar deja la
cookie {necessary,analytics:true,marketing:false} y /cookies lo refleja.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -262,6 +262,52 @@ textarea:focus {
|
|||||||
border-color: #5c2b2b;
|
border-color: #5c2b2b;
|
||||||
color: #d98c8c;
|
color: #d98c8c;
|
||||||
}
|
}
|
||||||
|
.uw-cookie-btn-save {
|
||||||
|
border-color: #b17c02;
|
||||||
|
color: #f0b93f;
|
||||||
|
}
|
||||||
|
.uw-cookie-btn-save:hover {
|
||||||
|
background: hsla(40, 90%, 45%, 0.15);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Panel «Personalizar» del banner (checkboxes por categoría). */
|
||||||
|
.uw-cookie-details {
|
||||||
|
margin-top: 14px;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid #352e2b;
|
||||||
|
}
|
||||||
|
.uw-cookie-category {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.uw-cookie-category label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.uw-cookie-category input[type='checkbox'] {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
accent-color: #d79602;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.uw-cookie-category input[type='checkbox']:disabled {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
.uw-cookie-cat-name {
|
||||||
|
color: #ebdec2;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.uw-cookie-category p {
|
||||||
|
color: #b1997f;
|
||||||
|
font-size: 13px;
|
||||||
|
margin: 2px 0 0 24px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
.uw-cookie-actions-detail {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Panel «Tu estado de consentimiento» en /cookies (datos de la API de Zaraz). */
|
/* Panel «Tu estado de consentimiento» en /cookies (datos de la API de Zaraz). */
|
||||||
.uw-consent-status {
|
.uw-consent-status {
|
||||||
|
|||||||
@@ -27,12 +27,11 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Categorías de consentimiento (necesarias siempre activas).
|
// Categorías de consentimiento (necesarias siempre activas).
|
||||||
type Category = { key: string; label: string; always?: boolean }
|
type Category = { key: string; label: string; always?: boolean; desc?: string }
|
||||||
export const CONSENT_CATEGORIES: readonly Category[] = [
|
export const CONSENT_CATEGORIES: readonly Category[] = [
|
||||||
{ key: 'necessary', label: 'Necesarias', always: true },
|
{ key: 'necessary', label: 'Necesarias', always: true, desc: 'Esenciales para el funcionamiento del sitio. No se pueden desactivar.' },
|
||||||
{ key: 'preferences', label: 'Preferencias' },
|
{ key: 'analytics', label: 'Analíticas', desc: 'Nos ayudan a entender cómo usas el sitio para mejorarlo.' },
|
||||||
{ key: 'analytics', label: 'Analíticas' },
|
{ key: 'marketing', label: 'Marketing', desc: 'Se utilizan para mostrarte anuncios relevantes.' },
|
||||||
{ key: 'marketing', label: 'Marketing' },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
type Consent = Record<string, boolean>
|
type Consent = Record<string, boolean>
|
||||||
@@ -79,12 +78,6 @@ function acceptAll() {
|
|||||||
function rejectAll() {
|
function rejectAll() {
|
||||||
writeConsent(allFlags(false))
|
writeConsent(allFlags(false))
|
||||||
}
|
}
|
||||||
/** Abre el modal granular de Zaraz; si no está, lleva a la página de cookies. */
|
|
||||||
function customize() {
|
|
||||||
const c = zaraz()
|
|
||||||
if (c) c.modal = true
|
|
||||||
else if (typeof window !== 'undefined') window.location.href = '/cookies'
|
|
||||||
}
|
|
||||||
function showBanner() {
|
function showBanner() {
|
||||||
window.dispatchEvent(new CustomEvent(SHOW_EVENT))
|
window.dispatchEvent(new CustomEvent(SHOW_EVENT))
|
||||||
}
|
}
|
||||||
@@ -101,12 +94,22 @@ function revokeConsent() {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
export function CookieBanner() {
|
export function CookieBanner() {
|
||||||
const [visible, setVisible] = useState(false)
|
const [visible, setVisible] = useState(false)
|
||||||
|
const [details, setDetails] = useState(false)
|
||||||
|
// Estado de los checkboxes granulares (categorías no necesarias).
|
||||||
|
const [prefs, setPrefs] = useState<Consent>({ analytics: false, marketing: false })
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.UWCookies = { showBanner, revokeConsent, acceptAll, rejectAll }
|
window.UWCookies = { showBanner, revokeConsent, acceptAll, rejectAll }
|
||||||
// Aparece si aún no hay decisión guardada.
|
// Precarga los checkboxes con lo ya guardado (si lo hay).
|
||||||
if (!readConsent()) setVisible(true)
|
const saved = readConsent()
|
||||||
const onShow = () => setVisible(true)
|
if (saved) setPrefs({ analytics: !!saved.analytics, marketing: !!saved.marketing })
|
||||||
|
else setVisible(true) // Aparece si aún no hay decisión guardada.
|
||||||
|
const onShow = () => {
|
||||||
|
const cur = readConsent()
|
||||||
|
if (cur) setPrefs({ analytics: !!cur.analytics, marketing: !!cur.marketing })
|
||||||
|
setDetails(false)
|
||||||
|
setVisible(true)
|
||||||
|
}
|
||||||
const onChange = () => {
|
const onChange = () => {
|
||||||
if (readConsent()) setVisible(false)
|
if (readConsent()) setVisible(false)
|
||||||
}
|
}
|
||||||
@@ -120,16 +123,50 @@ export function CookieBanner() {
|
|||||||
|
|
||||||
if (!visible) return null
|
if (!visible) return null
|
||||||
|
|
||||||
|
function savePrefs() {
|
||||||
|
writeConsent({ necessary: true, analytics: !!prefs.analytics, marketing: !!prefs.marketing })
|
||||||
|
setVisible(false)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="uw-cookie-content" role="dialog" aria-label="Consentimiento de cookies">
|
<div className="uw-cookie-content" role="dialog" aria-label="Consentimiento de cookies">
|
||||||
<div className="uw-cookie-text">
|
<div className="uw-cookie-text">
|
||||||
<h3>Utilizamos cookies</h3>
|
<h3>Utilizamos cookies</h3>
|
||||||
<p>Este sitio utiliza cookies propias y de terceros para garantizar el funcionamiento del sitio, analizar el tráfico y ofrecerte publicidad personalizada. Consulta nuestra política de cookies para más información.</p>
|
<p>Este sitio utiliza cookies propias y de terceros para garantizar el funcionamiento del sitio, analizar el tráfico y ofrecerte publicidad personalizada. Consulta nuestra política de cookies para más información.</p>
|
||||||
<Link href="/cookies" className="uw-cookie-link">Política de Cookies</Link>
|
<Link href="/cookies" className="uw-cookie-link">Política de Cookies</Link>
|
||||||
|
|
||||||
|
{details && (
|
||||||
|
<div className="uw-cookie-details" style={{ display: 'block' }}>
|
||||||
|
<div className="uw-cookie-category">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" checked disabled readOnly />
|
||||||
|
<span className="uw-cookie-cat-name">Necesarias</span>
|
||||||
|
</label>
|
||||||
|
<p>Esenciales para el funcionamiento del sitio. No se pueden desactivar.</p>
|
||||||
|
</div>
|
||||||
|
<div className="uw-cookie-category">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" id="uw-cookie-analytics" checked={!!prefs.analytics} onChange={(e) => setPrefs((s) => ({ ...s, analytics: e.target.checked }))} />
|
||||||
|
<span className="uw-cookie-cat-name">Analíticas</span>
|
||||||
|
</label>
|
||||||
|
<p>Nos ayudan a entender cómo usas el sitio para mejorarlo.</p>
|
||||||
|
</div>
|
||||||
|
<div className="uw-cookie-category">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" id="uw-cookie-marketing" checked={!!prefs.marketing} onChange={(e) => setPrefs((s) => ({ ...s, marketing: e.target.checked }))} />
|
||||||
|
<span className="uw-cookie-cat-name">Marketing</span>
|
||||||
|
</label>
|
||||||
|
<p>Se utilizan para mostrarte anuncios relevantes.</p>
|
||||||
|
</div>
|
||||||
|
<div className="uw-cookie-actions-detail">
|
||||||
|
<button type="button" className="uw-cookie-btn uw-cookie-btn-save" data-action="save" onClick={savePrefs}>Guardar preferencias</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="uw-cookie-actions">
|
<div className="uw-cookie-actions">
|
||||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-reject" data-action="reject" onClick={() => { rejectAll(); setVisible(false) }}>Rechazar</button>
|
<button type="button" className="uw-cookie-btn uw-cookie-btn-reject" data-action="reject" onClick={() => { rejectAll(); setVisible(false) }}>Rechazar</button>
|
||||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-customize" data-action="customize" onClick={customize}>Personalizar</button>
|
<button type="button" className="uw-cookie-btn uw-cookie-btn-customize" data-action="customize" onClick={() => setDetails((v) => !v)}>Personalizar</button>
|
||||||
<button type="button" className="uw-cookie-btn uw-cookie-btn-accept" data-action="accept" onClick={() => { acceptAll(); setVisible(false) }}>Aceptar todas</button>
|
<button type="button" className="uw-cookie-btn uw-cookie-btn-accept" data-action="accept" onClick={() => { acceptAll(); setVisible(false) }}>Aceptar todas</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user