Phase 7 (Spur D, E2 revidiert): KI-Vorprüfung VOR der Zahlung im Modal — rot lehnt ohne Zahlung ab, gelb/grün führt zum Stripe-Checkout (SinglePurchaseType::Change, 10 € netto), nach Zahlungseingang übernimmt der Webhook die geprüfte Fassung sofort (applyPaid: Snapshot, Sperre, Verlauf). Nur einmal je PM; Obergrenze legal.change_max_distance_percent (50 %) verhindert die verdeckte Selbst-Depublizierung. Phase 5 (Spur B): strukturiertes Schwärzungsformular mit Pflicht-Vorschau im verifizierten Web-Bereich UND als Modal im Kunden-Panel; Admin-Editor wird aus payload.redaction vorbefüllt. Umsetzungsmail LegalRequestExecuted an Antragsteller, Bestätigungsmail PressReleaseChangeApplied (Spur A/D, neuer abbestellbarer Typ press_release_corrected). Außerdem: - Re-Sync-Sperre + Sitemap-Invalidierung fest in depublish() verankert (Lücke im bezahlten Webhook-Pfad geschlossen) - Öffentliche „Rechtliches"-Seite als zweistufige Triage: primär der Portal-Anmeldelink, Formular nur Fallback mit Identifizierungs-Hinweis; Store auf report/dsgvo/personal_rights gehärtet - Panel-Button „Ändern/Melden" öffnet Anliegen-Modal (4 Spuren) statt des Web-Formulars - Pressekontakt-Fallback für Legacy-Bestände (30k PMs ohne Verknüpfung): Detailseite + pressContactEmail() nutzen PM-Kontakt → Firmen-Kontakt → Firmendaten - Korrektur-Gate entity-fest (Editor-Normalisierung zählt nicht als Änderung), toEditorHtml() in Admin-Edit + Korrektur-Panel, Wochenlimit-Hinweis in Text und Bremsen-Meldung Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
166 lines
11 KiB
PHP
166 lines
11 KiB
PHP
@extends('web.layouts.web-master')
|
|
|
|
@section('title', __('static.pm_report.concerns_title'))
|
|
@section('meta_description', __('static.pm_report.meta'))
|
|
|
|
@section('content')
|
|
<style>[x-cloak]{display:none!important}</style>
|
|
<x-web.static-page
|
|
:eyebrow="__('static.legal.eyebrow')"
|
|
:title="__('static.pm_report.concerns_title')"
|
|
:breadcrumb="__('static.pm_report.breadcrumb')"
|
|
>
|
|
<div class="max-w-[640px]">
|
|
<div class="mb-6 px-4 py-3 border border-bg-rule bg-bg-elev text-[13px] text-ink-2">
|
|
<p class="font-semibold text-ink mb-1">{{ $pressRelease->title }}</p>
|
|
<p>{{ __('static.pm_report.verified_as', ['email' => $contactEmail]) }}</p>
|
|
</div>
|
|
|
|
@if (session('pm-report-status'))
|
|
<div class="mb-6 px-4 py-3 border border-bg-rule bg-bg-elev text-[13px] text-ink-2" role="status">
|
|
{{ session('pm-report-status') }}
|
|
</div>
|
|
@endif
|
|
|
|
@if (($dsgvoPreview ?? null) !== null)
|
|
{{-- Pflicht-Diff (Spur B): Vorschau der Schwärzung bestätigen, bevor
|
|
die Anfrage entsteht. Ausführung bleibt beim Admin. --}}
|
|
@php
|
|
$fieldLabels = [
|
|
'title' => __('static.pm_report.dsgvo_field_title'),
|
|
'subtitle' => __('static.pm_report.dsgvo_field_subtitle'),
|
|
'text' => __('static.pm_report.dsgvo_field_text'),
|
|
'boilerplate_override' => __('static.pm_report.dsgvo_field_boilerplate'),
|
|
'keywords' => __('static.pm_report.dsgvo_field_keywords'),
|
|
];
|
|
@endphp
|
|
<div class="mb-6 border border-bg-rule">
|
|
<div class="px-4 py-3 bg-bg-elev border-b border-bg-rule">
|
|
<p class="text-[13px] font-semibold text-ink">{{ __('static.pm_report.dsgvo_preview_title') }}</p>
|
|
<p class="text-[12.5px] text-ink-2 mt-0.5">
|
|
{{ trans_choice('static.pm_report.dsgvo_preview_hits', (int) $dsgvoPreview['total_hits'], ['hits' => (int) $dsgvoPreview['total_hits']]) }}
|
|
</p>
|
|
</div>
|
|
<div class="px-4 py-3 space-y-4 text-[13px]">
|
|
@forelse ($dsgvoPreview['fields'] as $field => $meta)
|
|
<div>
|
|
<p class="text-[12px] font-semibold text-ink mb-1">
|
|
{{ $fieldLabels[$field] ?? $field }}
|
|
<span class="font-normal text-ink-3">· {{ trans_choice('static.pm_report.dsgvo_preview_field_hits', (int) $meta['hits'], ['hits' => (int) $meta['hits']]) }}</span>
|
|
</p>
|
|
<p class="text-ink-2 leading-relaxed whitespace-pre-line border-l-2 border-bg-rule pl-3">{{ \Illuminate\Support\Str::limit(trim(strip_tags((string) $meta['after'])), 600) }}</p>
|
|
</div>
|
|
@empty
|
|
<p class="text-ink-2">{{ __('static.pm_report.dsgvo_preview_no_text_hits') }}</p>
|
|
@endforelse
|
|
|
|
@if ($dsgvoInput['detach_contacts'])
|
|
<p class="text-ink-2">✓ {{ __('static.pm_report.dsgvo_preview_contacts') }}</p>
|
|
@endif
|
|
@if ($dsgvoInput['remove_images'])
|
|
<p class="text-ink-2">✓ {{ __('static.pm_report.dsgvo_preview_images') }}</p>
|
|
@endif
|
|
</div>
|
|
<div class="px-4 py-3 border-t border-bg-rule bg-bg-elev">
|
|
<form method="POST" action="{{ route('melden.pm.anliegen.store') }}" class="flex flex-wrap items-center gap-3">
|
|
@csrf
|
|
<input type="hidden" name="concern" value="dsgvo" />
|
|
<input type="hidden" name="confirmed" value="1" />
|
|
<input type="hidden" name="redaction_terms" value="{{ $dsgvoInput['redaction_terms'] }}" />
|
|
<input type="hidden" name="detach_contacts" value="{{ $dsgvoInput['detach_contacts'] ? 1 : 0 }}" />
|
|
<input type="hidden" name="remove_images" value="{{ $dsgvoInput['remove_images'] ? 1 : 0 }}" />
|
|
<input type="hidden" name="message" value="{{ $dsgvoInput['message'] }}" />
|
|
<button type="submit"
|
|
class="inline-flex items-center px-5 py-2.5 bg-brand text-white text-[13px] font-semibold hover:opacity-90">
|
|
{{ __('static.pm_report.dsgvo_preview_confirm') }}
|
|
</button>
|
|
<span class="text-[12.5px] text-ink-3">{{ __('static.pm_report.dsgvo_preview_edit_hint') }}</span>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
@php
|
|
$initialConcern = old('concern', isset($dsgvoInput) ? 'dsgvo' : '');
|
|
$prefilledTerms = old('redaction_terms', $dsgvoInput['redaction_terms'] ?? '');
|
|
$prefilledMessage = old('message', $dsgvoInput['message'] ?? '');
|
|
$prefilledDetach = old('detach_contacts', ($dsgvoInput['detach_contacts'] ?? false) ? '1' : null);
|
|
$prefilledRemoveImages = old('remove_images', ($dsgvoInput['remove_images'] ?? false) ? '1' : null);
|
|
@endphp
|
|
<form method="POST" action="{{ route('melden.pm.anliegen.store') }}" class="space-y-5"
|
|
x-data="{ concern: '{{ $initialConcern }}' }">
|
|
@csrf
|
|
|
|
<fieldset>
|
|
<legend class="block text-[12px] font-semibold text-ink mb-2">{{ __('static.pm_report.concern_legend') }}</legend>
|
|
<div class="space-y-2">
|
|
@foreach ([
|
|
'correction' => ['label' => __('static.pm_report.track_correction'), 'desc' => __('static.pm_report.track_correction_desc'), 'cost' => __('static.pm_report.cost_free')],
|
|
'dsgvo' => ['label' => __('static.pm_report.track_dsgvo'), 'desc' => __('static.pm_report.track_dsgvo_desc'), 'cost' => __('static.pm_report.cost_free')],
|
|
'depublication' => ['label' => __('static.pm_report.track_depublication'), 'desc' => __('static.pm_report.track_depublication_desc'), 'cost' => '35 €'],
|
|
'change' => ['label' => __('static.pm_report.track_change'), 'desc' => __('static.pm_report.track_change_desc'), 'cost' => '10 €'],
|
|
] as $value => $track)
|
|
<label class="flex items-start gap-3 border border-bg-rule px-3 py-2.5 cursor-pointer hover:bg-bg-elev">
|
|
<input type="radio" name="concern" value="{{ $value }}" required class="mt-0.5"
|
|
x-model="concern"
|
|
@checked($initialConcern === $value) />
|
|
<span class="text-[13px] text-ink">
|
|
<span class="font-semibold">{{ $track['label'] }}</span>
|
|
<span class="text-ink-3">· {{ $track['cost'] }}</span>
|
|
<span class="block text-[12.5px] text-ink-2">{{ $track['desc'] }}</span>
|
|
</span>
|
|
</label>
|
|
@endforeach
|
|
</div>
|
|
@error('concern')
|
|
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</fieldset>
|
|
|
|
{{-- Spur B (Phase 5): strukturierter Schwärzungsauftrag statt nur Freitext.
|
|
Wording bewusst „Schwärzung/Entfernung", nicht „Anonymisierung". --}}
|
|
<div x-cloak x-show="concern === 'dsgvo'" class="space-y-4 border border-bg-rule bg-bg-elev px-4 py-4">
|
|
<div>
|
|
<label for="redaction_terms" class="block text-[12px] font-semibold text-ink mb-1.5">{{ __('static.pm_report.dsgvo_terms_label') }}</label>
|
|
<textarea id="redaction_terms" name="redaction_terms" rows="4" maxlength="2000"
|
|
placeholder="{{ __('static.pm_report.dsgvo_terms_placeholder') }}"
|
|
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-brand">{{ $prefilledTerms }}</textarea>
|
|
<p class="mt-1 text-[12px] text-ink-3">{{ __('static.pm_report.dsgvo_terms_hint') }}</p>
|
|
@error('redaction_terms')
|
|
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
<label class="flex items-start gap-2.5 text-[13px] text-ink cursor-pointer">
|
|
<input type="checkbox" name="detach_contacts" value="1" class="mt-0.5" @checked($prefilledDetach) />
|
|
<span>{{ __('static.pm_report.dsgvo_detach_contacts') }}</span>
|
|
</label>
|
|
<label class="flex items-start gap-2.5 text-[13px] text-ink cursor-pointer">
|
|
<input type="checkbox" name="remove_images" value="1" class="mt-0.5" @checked($prefilledRemoveImages) />
|
|
<span>{{ __('static.pm_report.dsgvo_remove_images') }}</span>
|
|
</label>
|
|
<p class="text-[12px] text-ink-3 leading-relaxed">{{ __('static.pm_report.dsgvo_note') }}</p>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="message" class="block text-[12px] font-semibold text-ink mb-1.5">{{ __('static.pm_report.label_message') }}</label>
|
|
<textarea id="message" name="message" rows="6" required minlength="10" maxlength="5000"
|
|
placeholder="{{ __('static.pm_report.placeholder_message') }}"
|
|
class="w-full border border-bg-rule px-3 py-2.5 text-[13px] bg-white text-ink focus:outline-none focus:border-brand">{{ $prefilledMessage }}</textarea>
|
|
@error('message')
|
|
<p class="mt-1 text-[12px] text-red-600">{{ $message }}</p>
|
|
@enderror
|
|
</div>
|
|
|
|
<p class="text-[12.5px] text-ink-3 leading-relaxed">
|
|
{{ __('static.pm_report.concern_note') }}
|
|
</p>
|
|
|
|
<button type="submit"
|
|
class="inline-flex items-center px-5 py-2.5 bg-brand text-white text-[13px] font-semibold hover:opacity-90">
|
|
<span x-show="concern === 'dsgvo'" x-cloak>{{ __('static.pm_report.dsgvo_preview_button') }}</span>
|
|
<span x-show="concern !== 'dsgvo'">{{ __('static.pm_report.concern_submit') }}</span>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</x-web.static-page>
|
|
@endsection
|