where('workspace_id', $workspace->id) ->firstOrFail(); $this->pageId = $page->id; $this->workspaceUlid = $workspace->ulid; $apex = config('services.hetzner.zone', 'nimu.li'); if (! $workspace->isFreePlan() && $workspace->subdomain_full) { $this->publicUrlBase = "https://{$workspace->subdomain_full}/b"; $this->displayUrlBase = "{$workspace->subdomain_full}/b"; } else { $this->publicUrlBase = "https://{$apex}/b/{$workspace->slug}"; $this->displayUrlBase = "{$apex}/b/{$workspace->slug}"; } } public function save(array $state): void { $page = BioPage::findOrFail($this->pageId); $newSlug = $state['slug'] ?? $page->slug; $slugTaken = BioPage::where('workspace_id', $page->workspace_id) ->where('slug', $newSlug) ->where('id', '!=', $page->id) ->whereNull('deleted_at') ->exists(); if ($slugTaken) { $this->dispatch('toast', message: 'Slug "' . $newSlug . '" ist bereits vergeben.', type: 'error'); return; } if (! preg_match('/^[a-zA-Z0-9_-]{1,64}$/', $newSlug)) { $this->dispatch('toast', message: 'Slug: nur Buchstaben, Zahlen, - und _. Max 64 Zeichen.', type: 'error'); return; } $displayName = $state['profile']['displayName'] ?? ''; $page->update([ 'slug' => $newSlug, 'title' => ['en' => $displayName, 'de' => $displayName], 'is_published' => false, 'theme' => [ 'profile' => $state['profile'] ?? [], 'theme' => $state['theme'] ?? [], 'socials' => $state['socials'] ?? [], ], ]); BioBlock::where('bio_page_id', $this->pageId)->delete(); foreach ($state['blocks'] ?? [] as $i => $block) { BioBlock::create([ 'bio_page_id' => $this->pageId, 'position' => $i, 'type' => $block['type'] ?? 'link', 'config' => array_diff_key($block, array_flip(['id', 'type', '_collapsed'])), ]); } $this->dispatch('toast', message: 'Gespeichert', type: 'success'); } #[Renderless] public function checkSlug(string $slug): bool { $page = BioPage::findOrFail($this->pageId); return BioPage::where('workspace_id', $page->workspace_id) ->where('slug', $slug) ->where('id', '!=', $page->id) ->whereNull('deleted_at') ->exists(); } public function publish(array $state): void { $this->save($state); BioPage::where('id', $this->pageId)->update(['is_published' => true]); $this->dispatch('toast', message: 'Veröffentlicht', type: 'success'); } public function unpublish(): void { BioPage::where('id', $this->pageId)->update(['is_published' => false]); $this->dispatch('toast', message: 'Als Entwurf gespeichert', type: 'success'); } public function render(): View { $page = BioPage::with('blocks')->findOrFail($this->pageId); $theme = is_array($page->theme) ? $page->theme : []; $initialState = [ 'uid' => $page->blocks->count() + 100, 'slug' => $page->slug, 'isPublished' => $page->is_published, 'profile' => $theme['profile'] ?? [ 'avatar' => null, 'displayName' => $page->getTranslation('title', 'en'), 'handle' => $page->slug, 'bio' => '', 'verified' => false, ], 'theme' => array_merge([ 'bgType' => 'gradient', 'bg1' => '#0f0a2e', 'bg2' => '#6b1b9a', 'bgImage' => null, 'dark' => true, 'button' => 'rounded', 'font' => 'geist', 'borderColor' => '#7c3aed', 'shadowColor' => '#18181b', ], $theme['theme'] ?? []), 'socials' => $theme['socials'] ?? [], 'blocks' => $page->blocks ->sortBy('position') ->map(fn ($b) => array_merge( ['id' => $b->id, 'type' => $b->type], $b->config ?? [] )) ->values() ->toArray(), ]; return view('livewire.pages.bio.edit', [ 'page' => $page, 'workspaceUlid' => $this->workspaceUlid, 'bioUlid' => $page->ulid, 'initialState' => $initialState, 'publicUrlBase' => $this->publicUrlBase, 'displayUrlBase' => $this->displayUrlBase, ])->layout('layouts.nimuli-app', ['title' => 'Bio Editor']); } }