feat: cookie policy & consent banner per Moldova law 195/2024

- Settings page: new "Politica Cookie" section — toggle banner on/off,
  editable RO/RU policy text (defaults to full 14-section template)
- Public route GET /cookie-policy → CookiePolicyController returns
  locale-aware full policy page with tenant branding
- Cookie banner partial (Alpine.js, localStorage) shown on tracking and
  landing pages; Accept/Reject stores consent, banner dismisses
- Translation keys added to lang/ro/portal.php and lang/ru/portal.php
- Alpine.js (CDN) added to tracking and landing pages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-09-16 17:52:23 +00:00
parent 753e81d292
commit 68f58cbcdc
9 changed files with 591 additions and 0 deletions
+30
View File
@@ -83,6 +83,9 @@ class Settings extends Page
'ai_model_claude' => data_get($settings, 'ai.models.claude', \App\Services\Ai\AiAssistantService::MODEL_DEFAULTS['claude']),
'ai_model_gpt' => data_get($settings, 'ai.models.gpt', \App\Services\Ai\AiAssistantService::MODEL_DEFAULTS['gpt']),
'ai_model_gemini' => data_get($settings, 'ai.models.gemini', \App\Services\Ai\AiAssistantService::MODEL_DEFAULTS['gemini']),
'cookie_banner_enabled' => data_get($settings, 'cookie.banner_enabled', true),
'cookie_policy_ro' => data_get($settings, 'cookie.policy_ro', ''),
'cookie_policy_ru' => data_get($settings, 'cookie.policy_ru', ''),
]);
}
@@ -289,6 +292,28 @@ class Settings extends Page
->options(\App\Services\Ai\AiAssistantService::MODEL_OPTIONS['gemini'])
->default(\App\Services\Ai\AiAssistantService::MODEL_DEFAULTS['gemini']),
]),
Schemas\Components\Section::make(__('Politica Cookie'))
->description(__('Text afișat clienților conform Legii nr. 195/2024 (Moldova). Lasă gol pentru a folosi textul implicit. Folosiți [site], [email], [phone] ca variabile dinamice.'))
->columns(1)
->schema([
Forms\Components\Toggle::make('cookie_banner_enabled')
->label(__('Afișează banner cookie pe paginile publice'))
->helperText(__('Banner apare la prima vizită și poate fi acceptat/refuzat. Consimțământul se stochează în browser.'))
->default(true)
->columnSpanFull(),
Forms\Components\Textarea::make('cookie_policy_ro')
->label(__('Text politică cookie (RO)'))
->rows(15)
->placeholder(__('Lasă gol pentru textul implicit conform Legii 195/2024...'))
->helperText(__('Disponibil la /cookie-policy. Variabile: [site], [email], [phone]'))
->columnSpanFull(),
Forms\Components\Textarea::make('cookie_policy_ru')
->label(__('Text politică cookie (RU)'))
->rows(15)
->placeholder(__('Оставьте пустым для использования текста по умолчанию...'))
->helperText(__('Variabile: [site], [email], [phone]'))
->columnSpanFull(),
]),
])
->statePath('data');
}
@@ -353,6 +378,11 @@ class Settings extends Page
'gemini' => $data['ai_model_gemini'] ?? \App\Services\Ai\AiAssistantService::MODEL_DEFAULTS['gemini'],
],
],
'cookie' => [
'banner_enabled' => (bool) ($data['cookie_banner_enabled'] ?? true),
'policy_ro' => trim((string) ($data['cookie_policy_ro'] ?? '')) ?: null,
'policy_ru' => trim((string) ($data['cookie_policy_ru'] ?? '')) ?: null,
],
]),
]);