227 lines
8.6 KiB
PHP
227 lines
8.6 KiB
PHP
<?php
|
|
|
|
use App\Enums\Portal;
|
|
use App\Enums\PressReleaseStatus;
|
|
use App\Models\Category;
|
|
use App\Models\Company;
|
|
use App\Models\PressRelease;
|
|
use App\Services\Customer\CustomerCompanyContext;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Validation\Rule;
|
|
use Livewire\Attributes\Layout;
|
|
use Livewire\Attributes\Title;
|
|
use Livewire\Volt\Component;
|
|
|
|
new #[Layout('components.layouts.app'), Title('Neue Pressemitteilung')] class extends Component
|
|
{
|
|
public string $portal = 'presseecho';
|
|
|
|
public string $language = 'de';
|
|
|
|
public int|string|null $companyId = null;
|
|
|
|
public int|string|null $categoryId = null;
|
|
|
|
public string $title = '';
|
|
|
|
public string $text = '';
|
|
|
|
public string $keywords = '';
|
|
|
|
public string $backlinkUrl = '';
|
|
|
|
public function mount(): void
|
|
{
|
|
$user = auth()->user();
|
|
$context = app(CustomerCompanyContext::class);
|
|
$firstCompany = $context->selectedCompany($user) ?? $context->companiesFor($user)->first();
|
|
|
|
if ($firstCompany) {
|
|
$this->companyId = $firstCompany->id;
|
|
$this->portal = $firstCompany->portal?->value ?? Portal::Presseecho->value;
|
|
}
|
|
}
|
|
|
|
public function save(string $submitStatus = 'draft'): void
|
|
{
|
|
$this->validate([
|
|
'language' => ['required', Rule::in(['de', 'en'])],
|
|
'companyId' => ['required', 'integer'],
|
|
'categoryId' => ['required', 'integer', Rule::exists('categories', 'id')],
|
|
'title' => ['required', 'string', 'min:5', 'max:255'],
|
|
'text' => ['required', 'string', 'min:50'],
|
|
'keywords' => ['nullable', 'string', 'max:255'],
|
|
'backlinkUrl' => ['nullable', 'url', 'max:255'],
|
|
]);
|
|
|
|
$user = auth()->user();
|
|
$company = $this->selectedCompany();
|
|
|
|
if (! $company) {
|
|
$this->addError('companyId', __('Die gewählte Firma ist nicht Ihrem Account zugeordnet.'));
|
|
|
|
return;
|
|
}
|
|
|
|
$this->portal = $company->portal?->value ?? Portal::Presseecho->value;
|
|
|
|
$status = $submitStatus === 'review' ? PressReleaseStatus::Review : PressReleaseStatus::Draft;
|
|
|
|
$slug = (new PressRelease)->generateUniqueSlug($this->title, [
|
|
'portal' => $this->portal,
|
|
'language' => $this->language,
|
|
]);
|
|
|
|
$pr = PressRelease::query()->create([
|
|
'uuid' => (string) Str::uuid(),
|
|
'portal' => $this->portal,
|
|
'language' => $this->language,
|
|
'user_id' => $user->id,
|
|
'company_id' => (int) $this->companyId,
|
|
'category_id' => (int) $this->categoryId,
|
|
'title' => $this->title,
|
|
'slug' => $slug,
|
|
'text' => $this->text,
|
|
'keywords' => $this->keywords ?: null,
|
|
'backlink_url' => $this->backlinkUrl ?: null,
|
|
'status' => $status->value,
|
|
]);
|
|
|
|
session()->flash('success', $status === PressReleaseStatus::Review
|
|
? __('Pressemitteilung zur Prüfung eingereicht.')
|
|
: __('Entwurf gespeichert.'));
|
|
|
|
$this->redirect(route('me.press-releases.show', $pr->id), navigate: true);
|
|
}
|
|
|
|
public function with(): array
|
|
{
|
|
$user = auth()->user();
|
|
$context = app(CustomerCompanyContext::class);
|
|
$myCompanies = $context->companiesFor($user);
|
|
|
|
$categories = Category::query()
|
|
->with('translations')
|
|
->where('is_active', true)
|
|
->orderBy('id')
|
|
->get();
|
|
|
|
return [
|
|
'myCompanies' => $myCompanies,
|
|
'categories' => $categories,
|
|
'selectedPortalLabel' => $this->selectedCompany()?->portal?->label() ?? __('Wird aus der Firma übernommen'),
|
|
];
|
|
}
|
|
|
|
public function updatedCompanyId(): void
|
|
{
|
|
$company = $this->selectedCompany();
|
|
|
|
if ($company?->portal) {
|
|
$this->portal = $company->portal->value;
|
|
}
|
|
}
|
|
|
|
private function selectedCompany(): ?Company
|
|
{
|
|
return app(CustomerCompanyContext::class)
|
|
->findFor(auth()->user(), (int) $this->companyId);
|
|
}
|
|
}; ?>
|
|
|
|
<div class="space-y-6">
|
|
<flux:card>
|
|
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
|
<div>
|
|
<flux:heading size="lg">{{ __('Neue Pressemitteilung') }}</flux:heading>
|
|
<flux:subheading>{{ __('Entwurf erstellen oder direkt zur Prüfung einreichen.') }}</flux:subheading>
|
|
</div>
|
|
<flux:button variant="ghost" icon="arrow-left" href="{{ route('me.press-releases.index') }}" wire:navigate>
|
|
{{ __('Zurück') }}
|
|
</flux:button>
|
|
</div>
|
|
</flux:card>
|
|
|
|
<div class="grid gap-6 lg:grid-cols-[1fr,300px]">
|
|
<div class="space-y-6">
|
|
<flux:card>
|
|
<flux:heading size="md" class="mb-4">{{ __('Inhalt') }}</flux:heading>
|
|
<div class="space-y-4">
|
|
<flux:field>
|
|
<flux:label>{{ __('Titel') }} <span class="text-red-500">*</span></flux:label>
|
|
<flux:input wire:model="title" placeholder="{{ __('Aussagekräftiger Titel…') }}" />
|
|
<flux:error name="title" />
|
|
</flux:field>
|
|
|
|
<flux:field>
|
|
<flux:label>{{ __('Text') }} <span class="text-red-500">*</span></flux:label>
|
|
<flux:textarea wire:model="text" rows="16" placeholder="{{ __('Vollständiger Text…') }}" />
|
|
<flux:error name="text" />
|
|
</flux:field>
|
|
|
|
<flux:field>
|
|
<flux:label>{{ __('Stichwörter') }}</flux:label>
|
|
<flux:input wire:model="keywords" placeholder="{{ __('Kommagetrennt…') }}" />
|
|
</flux:field>
|
|
|
|
<flux:field>
|
|
<flux:label>{{ __('Backlink-URL') }}</flux:label>
|
|
<flux:input wire:model="backlinkUrl" type="url" placeholder="https://…" />
|
|
<flux:error name="backlinkUrl" />
|
|
</flux:field>
|
|
</div>
|
|
</flux:card>
|
|
</div>
|
|
|
|
<div class="space-y-4">
|
|
<flux:card>
|
|
<flux:heading size="sm" class="mb-3">{{ __('Metadaten') }}</flux:heading>
|
|
<div class="space-y-4">
|
|
<flux:field>
|
|
<flux:label>{{ __('Firma') }} <span class="text-red-500">*</span></flux:label>
|
|
<flux:select wire:model="companyId">
|
|
<option value="">{{ __('Bitte wählen…') }}</option>
|
|
@foreach($myCompanies as $c)
|
|
<option value="{{ $c->id }}">{{ $c->name }}</option>
|
|
@endforeach
|
|
</flux:select>
|
|
<flux:error name="companyId" />
|
|
</flux:field>
|
|
|
|
<flux:field>
|
|
<flux:label>{{ __('Kategorie') }} <span class="text-red-500">*</span></flux:label>
|
|
<flux:select wire:model="categoryId">
|
|
<option value="">{{ __('Bitte wählen…') }}</option>
|
|
@foreach($categories as $cat)
|
|
@php $catName = $cat->translations->firstWhere('locale', 'de')?->name ?? $cat->id; @endphp
|
|
<option value="{{ $cat->id }}">{{ $catName }}</option>
|
|
@endforeach
|
|
</flux:select>
|
|
<flux:error name="categoryId" />
|
|
</flux:field>
|
|
|
|
<flux:input :label="__('Portal')" :value="$selectedPortalLabel" disabled />
|
|
|
|
<flux:field>
|
|
<flux:label>{{ __('Sprache') }}</flux:label>
|
|
<flux:select wire:model="language">
|
|
<option value="de">Deutsch</option>
|
|
<option value="en">English</option>
|
|
</flux:select>
|
|
</flux:field>
|
|
</div>
|
|
</flux:card>
|
|
|
|
<flux:card>
|
|
<div class="space-y-2">
|
|
<flux:button type="button" variant="primary" class="w-full" wire:click="save('review')">
|
|
{{ __('Zur Prüfung einreichen') }}
|
|
</flux:button>
|
|
<flux:button type="button" variant="ghost" class="w-full" wire:click="save('draft')">
|
|
{{ __('Als Entwurf speichern') }}
|
|
</flux:button>
|
|
</div>
|
|
</flux:card>
|
|
</div>
|
|
</div>
|
|
</div>
|