diff --git a/docs/weiteres/Decision-Update Phase-2-Funktionen & Magic-Link-Änderungsprozess.md b/docs/weiteres/Decision-Update Phase-2-Funktionen & Magic-Link-Änderungsprozess.md index fb1d299..0824942 100644 --- a/docs/weiteres/Decision-Update Phase-2-Funktionen & Magic-Link-Änderungsprozess.md +++ b/docs/weiteres/Decision-Update Phase-2-Funktionen & Magic-Link-Änderungsprozess.md @@ -1,6 +1,6 @@ -**Version:** Juni 2026 (Rev. 2) **Datum:** 12.06.2026 **Status:** Abgestimmt – bereit zur Integration ins Konzept-/Decision-Log **Scope:** Definition von Boost und Veröffentlichungsnachweis (Launch), des Magic-Link-Zugangs- und Änderungsprozesses sowie der Phase-2-Funktionen (Vorab-Prüfung/Redigieren, Prüfzähler, höheres Prüfkontingent, kostenpflichtige Änderungspfade). **Änderungen Rev. 2:** KI bei E/F entfernt (Admin-Panel statt KI-Check); A nutzt Algorithmus-Diff statt KI; Bremsen-/Limit-Spalte für alle Pfade ergänzt. **Änderungen Rev. 3:** A & B als Launch bestätigt; Boost-Preisstaffel (12/20/35) und PDF-Preis (3 Credits) festgelegt; G Depublizieren = 25 Credits. +**Version:** Juni 2026 (Rev. 2) **Datum:** 12.06.2026 **Status:** Abgestimmt – bereit zur Integration ins Konzept-/Decision-Log **Scope:** Definition von Boost und Veröffentlichungsnachweis (Launch), des Magic-Link-Zugangs- und Änderungsprozesses sowie der Phase-2-Funktionen (Vorab-Prüfung/Redigieren, Prüfzähler, höheres Prüfkontingent, kostenpflichtige Änderungspfade). **Änderungen Rev. 2:** KI bei E/F entfernt (Admin-Panel statt KI-Check); A nutzt Algorithmus-Diff statt KI; Bremsen-/Limit-Spalte für alle Pfade ergänzt. **Änderungen Rev. 3:** A & B als Launch bestätigt; Boost-Preisstaffel (12/20/35) und PDF-Preis (3 Credits) festgelegt; G Depublizieren = 25 Credits. **Änderungen Rev. 4:** Extra-PM ergänzt – tier-gestaffelt (19/15/12/10/8 Credits); Cross-Portal-Veröffentlichung als kein Thema vermerkt (Portale getrennt). --- @@ -17,7 +17,27 @@ Dieses Update definiert die credit-nahen Funktionen und den Änderungsprozess f ## 2. Launch-Funktionen -### 2.1 Boost (Platzierung) +### 2.1 Extra-Pressemitteilung (Kontingent-Nachkauf) + +Die Brücke zwischen Tarif-Kontingent und Credit-Wallet: Ist das monatliche PM-Kontingent voll, kann eine einzelne weitere PM über die Wallet nachgekauft werden – ohne Zwang zum nächsthöheren Tarif. Das ist die faire Alternative zum erzwungenen Upgrade und der genau gewünschte Fall „ich brauche _einmalig_ eine PM mehr". + +**Preis ist tier-gestaffelt** (Treuevorteil: höheres Abo = günstigere Extra-PM): + +|Situation|Extra-PM|Inkl. PM-Preis|Logik| +|---|---|---|---| +|Kein Abo (Einzel)|19 Credits|19,00 €|voller Satz = Einzel-PM-Preis| +|Starter|15 Credits|9,67 €|günstiger als Einzel, mild über inkludiert| +|Business|12 Credits|4,90 €|–| +|Pro|10 Credits|3,96 €|–| +|Agency|8 Credits|3,32 €|–| + +**Mechanik:** Der Extra-PM-Preis wird **zur Kaufzeit aus dem aktiven Abo abgeleitet**, nicht statisch gespeichert. Reicht das Wallet-Guthaben nicht, greift der kontextuelle Mini-Checkout („Kostet 15 Credits, du hast 8" → Paket nachladen). Der Volumenrabatt steckt bereits in den Credit-Paketen – **keine** separaten Extra-PM-Bündel nötig (eine Wallet, ein tier-abhängiger Preis). + +**Design-Entscheidung (bewusst):** Der prozentuale Aufschlag ggü. dem inkludierten PM-Preis ist bei Starter am mildesten (+55 %), bei den oberen Tiers höher (~140–150 %). Das ist gewollt: Die gelegentliche 4. PM eines Starter-Kunden wird _nicht_ bestraft, um künstlichen Upgrade-Druck zu erzeugen – passt zur „fair bleiben, kein Zwang"-Linie. Wer dauerhaft viel veröffentlicht, wandert ohnehin in höhere Tiers. + +**Tageslimit gilt auch hier:** Nachgekaufte Extra-PMs unterliegen demselben Tageslimit wie das Kontingent (kein „Spam freikaufen"; höherer Tagesdurchsatz = Enterprise-Fall). + +### 2.2 Boost (Platzierung) - **Was:** bezahlte Hervorhebung einer PM – Platzierung auf Startseite und Branchen-/Kategorieseite - **Gate:** nur **grüne** PMs sind boostbar; gelb/rot nicht @@ -35,7 +55,7 @@ Dieses Update definiert die credit-nahen Funktionen und den Änderungsprozess f Moderate Staffel: Pro-Tag-Preis sinkt mit der Dauer, der Einstieg (7 Tage / 12) bleibt unter dem PM-Preis von 19 – ein Boost wirkt nie teurer als das Veröffentlichen selbst. Passt zur „Nische besetzen statt abschöpfen"-Linie (Volumen statt Einzelmarge). -### 2.2 Veröffentlichungsnachweis / PDF +### 2.3 Veröffentlichungsnachweis / PDF - **Was:** generiertes PDF „PM XY wurde am … auf … veröffentlicht" inkl. URL, Datum, Vorschau - **Zweck:** Reporting an Vorgesetzte/Kunden – klassische PR-Mitnahme @@ -173,8 +193,9 @@ Depublizieren bewusst am teuersten und mit Bedenkzeit, weil irreversibelste Akti --- -## 6. Offene Punkte -- **Kosten-Anker C/D** final bestätigen, sobald das Credit-/Prüf-System gebaut wird (aktuell ≈ 8 / ≈ 4 Credits). -**In Rev. 3 abgeschlossen:** A/B-Launch ✓ · Boost-Staffel 12/20/35 ✓ · PDF 3 Credits ✓ · G Depublizieren 25 Credits ✓ \ No newline at end of file +**Bewusst nicht im Scope – Cross-Portal-Veröffentlichung:** Die beiden Portale (presseecho.de, businessportal24.com) sind optisch, inhaltlich und systemisch vollständig getrennt; im Relaunch laufen sie lediglich auf einem gemeinsamen Backend zusammen. Eine PM auf beiden Portalen gleichzeitig zu veröffentlichen ist **kein Feature** – wer in beiden präsent sein will, bucht zwei getrennte Einträge (zwei Slots / zwei Extra-PMs). Das vermeidet Duplicate-Content über die eigenen Domains und passt zur getrennten Zielgruppen-Logik. Kein Phase-2-Punkt, sondern bewusst ausgeschlossen. +Noch mal ein wichtiger Hintergrund, der noch dokumentiert werden muss. Das sollte auch zukünftig gegebenenfalls geprüft werden. + +**In Rev. 3 abgeschlossen:** A/B-Launch ✓ · Boost-Staffel 12/20/35 ✓ · PDF 3 Credits ✓ · G Depublizieren 25 Credits ✓ **In Rev. 4 abgeschlossen:** Extra-PM tier-gestaffelt (19/15/12/10/8) ✓ · Cross-Portal ausgeschlossen ✓ \ No newline at end of file diff --git a/resources/views/livewire/customer/press-releases/show.blade.php b/resources/views/livewire/customer/press-releases/show.blade.php index bc3570a..bb1b330 100644 --- a/resources/views/livewire/customer/press-releases/show.blade.php +++ b/resources/views/livewire/customer/press-releases/show.blade.php @@ -99,8 +99,13 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends $cover = app(PressReleaseCoverImage::class); $user = auth()->user(); + $company = $pr->company?->loadCount(['pressReleases', 'contacts']); + return [ 'pr' => $pr, + 'companyLogoUrl' => $company?->logoUrl(), + 'companyInitials' => $this->companyInitials($company?->name), + 'companyMetaLine' => $this->companyMetaLine($company), 'categoryName' => $categoryName, 'coverUrl' => $cover->coverUrl($pr, 'cover'), 'coverIsPlaceholder' => $cover->coverIsPlaceholder($pr), @@ -122,12 +127,59 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends ]; } + /** + * Initialen für die Logo-Kachel (analog zur Firmenübersicht). + */ + private function companyInitials(?string $name): string + { + $name = trim((string) $name); + + if ($name === '') { + return '–'; + } + + $letters = collect(preg_split('/\s+/u', $name) ?: []) + ->map(fn (string $word): string => mb_substr($word, 0, 1)) + ->filter() + ->take(2) + ->implode(''); + + return mb_strtoupper($letters ?: mb_substr($name, 0, 2)); + } + + /** + * Kompakte Meta-Zeile: Ort (letzte Adresszeile) · Firmentyp. + */ + private function companyMetaLine(?\App\Models\Company $company): string + { + if (! $company) { + return ''; + } + + $parts = []; + + $lastAddressLine = collect(preg_split('/\r?\n/', trim((string) $company->address)) ?: []) + ->map(fn ($line) => trim((string) $line)) + ->filter() + ->last(); + + if (is_string($lastAddressLine) && $lastAddressLine !== '') { + $parts[] = $lastAddressLine; + } + + if ($company->type?->label()) { + $parts[] = $company->type->label(); + } + + return implode(' · ', $parts); + } + private function getMyPR(): PressRelease { return PressRelease::withoutGlobalScopes() ->where('user_id', auth()->id()) ->with([ - 'company:id,name,email,phone', + 'company:id,name,email,phone,address,portal,logo_path,legacy_portal,is_active,type', 'category.translations', 'contacts' => fn ($query) => $query ->withoutGlobalScopes() @@ -314,16 +366,30 @@ new #[Layout('components.layouts.app'), Title('Pressemitteilung')] class extends {{ __('Firma & Pressekontakt') }}