workspaceUlid = require_workspace()->ulid; } public function updated(string $prop): void { $this->dispatch('qr-preview-update', payload: $this->buildPayload(), style: [ 'fg' => $this->fgColor, 'bg' => $this->bgColor, 'dotStyle' => $this->dotStyle, 'cornerSquare' => $this->cornerSquare, 'cornerDot' => $this->cornerDot, 'margin' => $this->margin, 'ec' => $this->errorCorrection, 'logoUrl' => $this->logoUrl ?: null, 'useGradient' => $this->gradientEnabled, 'gradStart' => $this->gradStart, 'gradEnd' => $this->gradEnd, 'logoSize' => $this->logoSize / 100, 'logoMargin' => $this->logoMargin, 'hideDots' => $this->hideDots, ] ); } public function buildPayload(): string { return match ($this->type) { 'email' => 'mailto:'.trim($this->emailTo).'?subject='.urlencode($this->emailSubject).'&body='.urlencode($this->emailBody), 'phone' => 'tel:'.trim($this->url), 'sms' => 'SMSTO:'.trim($this->smsTo).':'.$this->smsBody, 'vcard' => $this->buildVcard(), 'wifi' => $this->buildWifi(), 'text' => $this->textContent, default => $this->normalizeUrl(trim($this->url)), }; } private function buildVcard(): string { return implode("\n", array_filter([ 'BEGIN:VCARD', 'VERSION:3.0', $this->vcardName ? "FN:{$this->vcardName}" : null, $this->vcardPhone ? "TEL:{$this->vcardPhone}" : null, $this->vcardEmail ? "EMAIL:{$this->vcardEmail}" : null, $this->vcardCompany ? "ORG:{$this->vcardCompany}" : null, $this->vcardWebsite ? "URL:{$this->vcardWebsite}" : null, 'END:VCARD', ])); } private function buildWifi(): string { $enc = $this->wifiEncryption ?: 'nopass'; $hidden = $this->wifiHidden ? 'true' : 'false'; return "WIFI:T:{$enc};S:{$this->wifiSsid};P:{$this->wifiPassword};H:{$hidden};;"; } private function normalizeUrl(string $url): string { if ($url && !preg_match('/^https?:\/\//i', $url)) { return 'https://' . $url; } return $url; } public function save(): void { $urlRule = match ($this->type) { 'url' => 'required|url|max:2048', 'phone' => 'required|max:50', 'email' => 'nullable', default => 'nullable', }; $this->validate([ 'type' => 'required|in:url,vcard,wifi,text,email,phone,sms', 'label' => 'nullable|max:200', 'url' => $urlRule, 'emailTo' => $this->type === 'email' ? 'required|email|max:200' : 'nullable', 'smsTo' => $this->type === 'sms' ? 'required|max:50' : 'nullable', 'vcardName' => $this->type === 'vcard' ? 'required|max:200' : 'nullable', 'wifiSsid' => $this->type === 'wifi' ? 'required|max:200' : 'nullable', 'fgColor' => ['required', 'regex:/^#[0-9a-fA-F]{6}$/'], 'bgColor' => ['required', 'regex:/^#[0-9a-fA-F]{6}$/'], 'logoUrl' => 'nullable|url|max:2048', 'errorCorrection' => 'in:L,M,Q,H', 'frame' => 'in:none,label-bottom,label-top', 'gradStart' => ['nullable', 'regex:/^#[0-9a-fA-F]{6}$/'], 'gradEnd' => ['nullable', 'regex:/^#[0-9a-fA-F]{6}$/'], ]); $workspace = Workspace::where('ulid', $this->workspaceUlid)->firstOrFail(); $dbType = match ($this->type) { 'email', 'phone', 'sms' => 'url', default => $this->type, }; QrCode::create([ 'workspace_id' => $workspace->id, 'type' => $dbType, 'payload' => [ 'data' => $this->buildPayload(), 'label' => $this->label ?: null, 'display_type' => $this->type, ], 'style' => [ 'fg_color' => $this->fgColor, 'bg_color' => $this->bgColor, 'logo_url' => $this->logoUrl ?: null, 'dot_style' => $this->dotStyle, 'corner_square' => $this->cornerSquare, 'corner_dot' => $this->cornerDot, 'size' => $this->size, 'margin' => $this->margin, 'error_correction' => $this->errorCorrection, 'gradient_enabled' => $this->gradientEnabled, 'grad_start' => $this->gradStart, 'grad_end' => $this->gradEnd, 'logo_size' => $this->logoSize, 'logo_margin' => $this->logoMargin, 'hide_dots' => $this->hideDots, 'frame' => $this->frame, 'frame_text' => $this->frameText ?: null, 'frame_color' => $this->frameColor, ], 'is_dynamic' => $this->isDynamic, 'scan_limit' => $this->scanLimit ?: null, 'expires_at' => $this->expiresAt ?: null, ]); $this->dispatch('toast', message: 'QR-Code erstellt', type: 'success'); $this->redirect(route('w.qr.index', $workspace->ulid), navigate: true); } public function render(): View { return view('livewire.pages.qr-codes.create') ->layout('layouts.nimuli-app', ['title' => 'QR Code erstellen']); } }