*/ public array $variants = []; public function mount(string $linkUlid): void { $link = Link::where('ulid', $linkUlid)->firstOrFail(); $this->linkUlid = $linkUlid; $this->linkId = $link->id; $this->linkTarget = $link->target_url; $existing = $link->variants()->orderBy('id')->get(); if ($existing->isEmpty()) { $this->variants = [ ['id' => null, 'label' => 'Variant A', 'target_url' => $link->target_url, 'weight' => 50], ['id' => null, 'label' => 'Variant B', 'target_url' => '', 'weight' => 50], ]; } else { $this->variants = $existing->map(fn ($v) => [ 'id' => $v->id, 'label' => $v->label, 'target_url' => $v->target_url, 'weight' => $v->weight, ])->toArray(); } } public function addVariant(): void { if (count($this->variants) >= 5) { return; } $this->variants[] = [ 'id' => null, 'label' => 'Variant ' . chr(64 + count($this->variants) + 1), 'target_url' => '', 'weight' => 0, ]; $this->rebalanceWeights(); } public function removeVariant(int $index): void { if (count($this->variants) <= 2) { return; } array_splice($this->variants, $index, 1); $this->rebalanceWeights(); } public function rebalanceWeights(): void { $count = count($this->variants); if ($count === 0) { return; } $base = intdiv(100, $count); $remainder = 100 - ($base * $count); foreach ($this->variants as $i => &$variant) { $variant['weight'] = $base + ($i === 0 ? $remainder : 0); } unset($variant); } public function save(): void { $this->validate([ 'variants' => 'required|array|min:2|max:5', 'variants.*.label' => 'required|string|max:64', 'variants.*.target_url' => 'required|url|max:2048', 'variants.*.weight' => 'required|integer|min:1|max:99', ]); $totalWeight = array_sum(array_column($this->variants, 'weight')); if ($totalWeight !== 100) { $this->addError('variants', 'Weights must sum to 100%.'); return; } $existingIds = collect($this->variants)->pluck('id')->filter()->values()->all(); LinkVariant::where('link_id', $this->linkId) ->whereNotIn('id', $existingIds) ->delete(); foreach ($this->variants as $v) { if ($v['id']) { LinkVariant::where('id', $v['id'])->update([ 'label' => $v['label'], 'target_url' => $v['target_url'], 'weight' => $v['weight'], ]); } else { LinkVariant::create([ 'link_id' => $this->linkId, 'label' => $v['label'], 'target_url' => $v['target_url'], 'weight' => $v['weight'], ]); } } $this->dispatch('toast', message: 'A/B variants saved', type: 'success'); $this->closeModal(); } public static function modalMaxWidth(): string { return 'xl'; } public function render(): View { return view('livewire.modals.link-variants'); } }