newsroom: Beschreibung pflegen, durch die Rot-Ebene geprüft (Roadmap 1b.3)
Die Firmenseite im Kundenbereich bekommt den Beschreibungstext (max. 2 000 Zeichen, reiner Text). Er läuft durch dieselbe Klassifikation wie eine Meldung (CompanyProfileCheck, KI mit deterministischem Fallback); Rot wird abgewiesen. Links im Profiltext gibt es nicht — die Website ist das eine Link-Feld. Bilder zurückgestellt (BALD-Platzhalter), bis die Bild-Kennzeichnung angepasst ist. Stufe 3 der Konversionsleiter (newsroom_edited) wird hier geschrieben, einmal je Firma, mit der Herkunft des zuletzt eingelösten Magic Links. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
079477a423
commit
87f95fb7a7
6 changed files with 253 additions and 2 deletions
|
|
@ -3,8 +3,11 @@
|
|||
use App\Models\Company;
|
||||
use App\Models\Contact;
|
||||
use App\Models\PressRelease;
|
||||
use App\Services\Company\CompanyProfileCheck;
|
||||
use App\Services\Conversion\ConversionRecorder;
|
||||
use App\Services\Customer\CustomerCompanyContext;
|
||||
use App\Services\Image\ImageService;
|
||||
use App\Support\WebCaches;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Livewire\Attributes\Layout;
|
||||
|
|
@ -33,6 +36,8 @@ new #[Layout('components.layouts.app'), Title('Firma')] class extends Component
|
|||
|
||||
public string $companyCountryCode = 'DE';
|
||||
|
||||
public string $companyBoilerplate = '';
|
||||
|
||||
public bool $companyDisableFooterCode = false;
|
||||
|
||||
public $companyLogo = null;
|
||||
|
|
@ -76,6 +81,7 @@ new #[Layout('components.layouts.app'), Title('Firma')] class extends Component
|
|||
$this->companyPhone = (string) ($company->phone ?? '');
|
||||
$this->companyWebsite = (string) ($company->website ?? '');
|
||||
$this->companyCountryCode = (string) ($company->country_code ?? 'DE');
|
||||
$this->companyBoilerplate = (string) ($company->boilerplate ?? '');
|
||||
$this->companyDisableFooterCode = (bool) $company->disable_footer_code;
|
||||
$this->companyLogo = null;
|
||||
$this->removeCompanyLogo = false;
|
||||
|
|
@ -87,7 +93,7 @@ new #[Layout('components.layouts.app'), Title('Firma')] class extends Component
|
|||
$this->resetCompanyForm();
|
||||
}
|
||||
|
||||
public function saveCompany(ImageService $imageService): void
|
||||
public function saveCompany(ImageService $imageService, CompanyProfileCheck $profileCheck, ConversionRecorder $conversions): void
|
||||
{
|
||||
$company = $this->company();
|
||||
$this->authorize('update', $company);
|
||||
|
|
@ -99,9 +105,22 @@ new #[Layout('components.layouts.app'), Title('Firma')] class extends Component
|
|||
'companyPhone' => ['nullable', 'string', 'max:40'],
|
||||
'companyWebsite' => ['nullable', 'url', 'max:190'],
|
||||
'companyCountryCode' => ['nullable', 'string', 'size:2', Rule::in(array_keys((array) config('countries.items', [])))],
|
||||
// Reiner Text (Roadmap 1b.3): Links im Profiltext sind nicht
|
||||
// vorgesehen — sonst wird das Profil ein Backlink-Automat. Die
|
||||
// Website ist das eine, systemseitig ausgezeichnete Link-Feld.
|
||||
'companyBoilerplate' => ['nullable', 'string', 'max:2000'],
|
||||
'companyLogo' => ['nullable', 'image', 'max:' . (int) (ImageService::MAX_LOGO_BYTES / 1024)],
|
||||
]);
|
||||
|
||||
$boilerplate = trim(strip_tags((string) $validated['companyBoilerplate']));
|
||||
|
||||
// Rot-Ebene der bestehenden Prüfung — dieselbe wie für eine Meldung.
|
||||
if ($boilerplate !== '' && $boilerplate !== trim((string) $company->boilerplate) && $profileCheck->isRed($company, $boilerplate)) {
|
||||
throw ValidationException::withMessages([
|
||||
'companyBoilerplate' => __('Die Beschreibung enthält unzulässige Inhalte und kann so nicht gespeichert werden.'),
|
||||
]);
|
||||
}
|
||||
|
||||
$company->fill([
|
||||
'name' => $validated['companyName'],
|
||||
'address' => $validated['companyAddress'] ?: null,
|
||||
|
|
@ -109,6 +128,7 @@ new #[Layout('components.layouts.app'), Title('Firma')] class extends Component
|
|||
'phone' => $validated['companyPhone'] ?: null,
|
||||
'website' => $validated['companyWebsite'] ?: null,
|
||||
'country_code' => $validated['companyCountryCode'] ?: null,
|
||||
'boilerplate' => $boilerplate !== '' ? $boilerplate : null,
|
||||
'disable_footer_code' => $this->companyDisableFooterCode,
|
||||
]);
|
||||
|
||||
|
|
@ -130,6 +150,13 @@ new #[Layout('components.layouts.app'), Title('Firma')] class extends Component
|
|||
$company->save();
|
||||
$this->resetCompanyForm();
|
||||
|
||||
// Stufe 3 der Konversionsleiter: Newsroom gepflegt (einmal je Firma).
|
||||
$conversions->recordNewsroomEdited($company, auth()->user());
|
||||
|
||||
// Der öffentliche Newsroom zeigt Name, Logo und Beschreibung — die
|
||||
// Änderung soll nicht erst nach Ablauf des Seiten-Caches sichtbar sein.
|
||||
WebCaches::forgetPublicPages();
|
||||
|
||||
session()->flash('company-status', __('Stammdaten wurden gespeichert.'));
|
||||
}
|
||||
|
||||
|
|
@ -269,6 +296,7 @@ new #[Layout('components.layouts.app'), Title('Firma')] class extends Component
|
|||
$this->companyPhone = '';
|
||||
$this->companyWebsite = '';
|
||||
$this->companyCountryCode = 'DE';
|
||||
$this->companyBoilerplate = '';
|
||||
$this->companyDisableFooterCode = false;
|
||||
$this->companyLogo = null;
|
||||
$this->removeCompanyLogo = false;
|
||||
|
|
@ -416,6 +444,11 @@ new #[Layout('components.layouts.app'), Title('Firma')] class extends Component
|
|||
<flux:textarea wire:model="companyAddress" :label="__('Adresse')" rows="3" />
|
||||
<flux:error name="companyAddress" />
|
||||
</flux:field>
|
||||
<flux:field class="sm:col-span-2">
|
||||
<flux:textarea wire:model="companyBoilerplate" :label="__('Beschreibung')" rows="5" maxlength="2000"
|
||||
:description="__('Kurzporträt des Unternehmens — erscheint im Newsroom und unter jeder Meldung als „Über das Unternehmen“. Reiner Text, keine Links; die Website steht im eigenen Feld.')" />
|
||||
<flux:error name="companyBoilerplate" />
|
||||
</flux:field>
|
||||
<flux:field>
|
||||
<flux:select wire:model="companyCountryCode" :label="__('Land')">
|
||||
@foreach ($countries as $code => $name)
|
||||
|
|
@ -471,6 +504,19 @@ new #[Layout('components.layouts.app'), Title('Firma')] class extends Component
|
|||
</flux:field>
|
||||
</div>
|
||||
|
||||
{{-- Bilder im Newsroom: zurückgestellt, bis die Bild-Kennzeichnung
|
||||
angepasst ist (Entscheidung 15.09.2026). Sichtbar als BALD,
|
||||
nicht weggelassen — Leitplanke der Roadmap. --}}
|
||||
<div class="mt-5 pt-4 border-t border-[color:var(--color-bg-rule)] space-y-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-[11px] uppercase tracking-[0.6px] text-[color:var(--color-ink-3)] font-semibold">{{ __('Bilder im Newsroom') }}</span>
|
||||
<flux:badge size="sm" color="zinc">{{ __('BALD') }}</flux:badge>
|
||||
</div>
|
||||
<p class="text-[12.5px] text-[color:var(--color-ink-3)] m-0">
|
||||
{{ __('Funktion folgt. Bilder im Newsroom unterliegen derselben KI-Kennzeichnung wie Bilder in Meldungen; die wird gerade überarbeitet.') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 pt-4 border-t border-[color:var(--color-bg-rule)] flex justify-end gap-2">
|
||||
<flux:button type="button" variant="filled" wire:click="cancelCompanyForm">
|
||||
{{ __('Abbrechen') }}
|
||||
|
|
@ -510,6 +556,10 @@ new #[Layout('components.layouts.app'), Title('Firma')] class extends Component
|
|||
<dt class="text-[11px] uppercase tracking-[0.6px] text-[color:var(--color-ink-3)] font-semibold mb-1">{{ __('Adresse') }}</dt>
|
||||
<dd class="text-[color:var(--color-ink)] whitespace-pre-line">{{ $company->address ?: '–' }}</dd>
|
||||
</div>
|
||||
<div class="sm:col-span-2">
|
||||
<dt class="text-[11px] uppercase tracking-[0.6px] text-[color:var(--color-ink-3)] font-semibold mb-1">{{ __('Beschreibung') }}</dt>
|
||||
<dd class="text-[color:var(--color-ink)] whitespace-pre-line">{{ $company->boilerplate ?: '–' }}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</article>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue