feat: complete cookie consent with categories & technical processing

- Full 4-category consent modal: Necesare (locked) / Funcționale /
  Analitice / Marketing with toggle switches per category
- Banner shows simple view first; "Personalizează" opens detailed panel
- Consent stored as JSON in localStorage (cookie_consent_v2)
- window.cookieConsent object set on load; dispatches
  cookie-consent-updated / cookie-analytics-granted / cookie-marketing-granted
  CustomEvents for deferred script loading
- Floating 🍪 FAB button lets users re-open settings at any time
- Policy page: "Personalizează" button resets consent, reopens modal
- Full RO/RU translation for all categories and UI strings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-09-17 20:39:13 +00:00
parent 68f58cbcdc
commit c3e4b99d4b
5 changed files with 284 additions and 100 deletions
+31 -6
View File
@@ -13,13 +13,16 @@
header { background: {{ $themeColor }}; color: #fff; padding: 28px 16px; text-align: center; }
header img { max-height: 48px; margin-bottom: 10px; display: block; margin-inline: auto; }
header h1 { font-size: 20px; font-weight: 700; }
.wrap { max-width: 760px; margin: 0 auto; padding: 24px 16px 64px; }
.wrap { max-width: 760px; margin: 0 auto; padding: 24px 16px 80px; }
.card { background: #fff; border-radius: 12px; padding: 28px 24px; margin-top: 16px; box-shadow: 0 1px 3px rgba(0,0,0,.05); }
.card h2 { font-size: 15px; font-weight: 700; margin-bottom: 12px; color: {{ $themeColor }}; letter-spacing: .02em; }
.policy-text { font-size: 14px; white-space: pre-wrap; color: #374151; line-height: 1.7; }
.card-title { font-size: 16px; font-weight: 700; margin-bottom: 14px; color: {{ $themeColor }}; }
.policy-text { font-size: 13.5px; white-space: pre-wrap; color: #374151; line-height: 1.75; }
.back-link { display: inline-flex; align-items: center; gap: 6px; color: {{ $themeColor }}; text-decoration: none; font-size: 14px; font-weight: 500; margin-bottom: 8px; }
.back-link:hover { opacity: .8; }
.manage-btn { display: inline-flex; align-items: center; gap: 6px; background: {{ $themeColor }}; color: #fff; border: none; padding: 10px 20px; border-radius: 8px; font-size: 14px; font-weight: 600; cursor: pointer; text-decoration: none; }
.manage-btn:hover { opacity: .9; }
footer { text-align: center; padding: 24px 16px; color: #9ca3af; font-size: 12px; }
[x-cloak] { display: none !important; }
@media (prefers-color-scheme: dark) {
body { background: #0f172a; color: #e5e7eb; }
.card { background: #1e293b; box-shadow: none; }
@@ -27,6 +30,7 @@
footer { color: #64748b; }
}
</style>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body>
<header>
@@ -37,19 +41,40 @@
</header>
<div class="wrap">
<a href="{{ url()->previous('/') }}" class="back-link">
<a href="javascript:history.back()" class="back-link">
<svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.2" viewBox="0 0 24 24">
<path stroke-linecap="round" d="M15 19l-7-7 7-7"/>
</svg>
{{ __('portal.cookie.back') }}
</a>
<div class="card">
<h2>{{ __('portal.cookie.policy_title') }}</h2>
<div class="card" style="margin-bottom:12px;">
<p class="card-title">{{ __('portal.cookie.policy_title') }}</p>
<p class="policy-text">{{ $policyText }}</p>
</div>
<div class="card" style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;">
<div>
<p style="font-size:14px;font-weight:600;color:#111827;margin-bottom:2px;">{{ __('portal.cookie.manage_title') }}</p>
<p style="font-size:13px;color:#6b7280;">{{ __('portal.cookie.settings_body') }}</p>
</div>
<button class="manage-btn" onclick="openCookieSettings()">
🍪 {{ __('portal.cookie.customize') }}
</button>
</div>
<footer>{{ __('portal.common.powered_by') }}</footer>
</div>
@php $themeColor = $themeColor ?? '#3B82F6'; @endphp
@include('partials.cookie-banner')
<script>
function openCookieSettings() {
// Reset consent so the banner re-appears with settings panel open
localStorage.removeItem('cookie_consent_v2');
location.reload();
}
</script>
</body>
</html>