'', 'enabled' => true, 'event' => 'ticket_created', 'conditions' => [], 'actions' => [], ]; public bool $templateFormOpen = false; public ?int $editingTemplateId = null; public array $templateForm = ['name' => '', 'subject' => '', 'body' => '']; public static function eventLabels(): array { return [ 'ticket_created' => 'Zgłoszenie utworzone', 'ticket_updated' => 'Zgłoszenie zaktualizowane (dowolne pole)', 'status_changed' => 'Zmiana statusu', 'priority_changed' => 'Zmiana priorytetu', 'assignee_changed' => 'Zmiana przypisanego operatora', 'team_changed' => 'Zmiana zespołu', 'category_changed' => 'Zmiana kategorii', 'comment_added' => 'Nowa wiadomość (publiczna)', ]; } public static function fieldLabels(): array { return [ 'status_key' => 'Status', 'priority_key' => 'Priorytet', 'team_id' => 'Zespół', 'subcategory_id' => 'Podkategoria', 'assignee_id' => 'Operator przypisany', 'customer_id' => 'Zgłaszający', 'subject' => 'Temat', 'body' => 'Treść', ]; } public static function operatorLabels(): array { return [ 'equals' => 'jest równe', 'not_equals' => 'jest różne od', 'is_empty' => 'jest puste', 'is_not_empty' => 'nie jest puste', 'contains' => 'zawiera', ]; } public static function actionTypeLabels(): array { return [ 'set_status' => 'Ustaw status', 'set_priority' => 'Ustaw priorytet', 'set_team' => 'Ustaw zespół', 'set_assignee' => 'Ustaw operatora', 'send_notification' => 'Wyślij powiadomienie e-mail', ]; } #[Computed] public function triggers(): Collection { return Trigger::query()->orderBy('sort_order')->get(); } #[Computed] public function statuses(): Collection { return Status::query()->orderBy('sort_order')->get(); } #[Computed] public function priorities(): Collection { return Priority::query()->orderBy('sort_order')->get(); } #[Computed] public function teams(): Collection { return Team::query()->orderBy('name')->get(); } #[Computed] public function operators(): Collection { return User::query()->whereHas('roleAssignments', fn ($q) => $q->whereIn('key', ['operator', 'admin']))->orderBy('name')->get(); } #[Computed] public function subcategories(): Collection { return Subcategory::query()->with('category')->get() ->sortBy(fn (Subcategory $s) => $s->category->name.' / '.$s->name, SORT_NATURAL | SORT_FLAG_CASE) ->values(); } #[Computed] public function customers(): Collection { return User::query()->whereHas('roleAssignments', fn ($q) => $q->where('key', 'client'))->orderBy('name')->get(); } #[Computed] public function emailTemplates(): Collection { return TriggerEmailTemplate::query()->orderBy('name')->get(); } public function openForm(): void { $this->editingId = null; $this->form = ['name' => '', 'enabled' => true, 'event' => 'ticket_created', 'conditions' => [], 'actions' => []]; $this->resetErrorBag(); $this->formOpen = true; } public function editTrigger(int $id): void { $trigger = Trigger::query()->findOrFail($id); $this->editingId = $trigger->id; $this->form = [ 'name' => $trigger->name, 'enabled' => $trigger->enabled, 'event' => $trigger->event, 'conditions' => $trigger->conditions, 'actions' => $trigger->actions, ]; $this->resetErrorBag(); $this->formOpen = true; } public function closeForm(): void { $this->formOpen = false; } public function addCondition(): void { $this->form['conditions'][] = ['field' => Trigger::CONDITION_FIELDS[0], 'operator' => 'equals', 'value' => '']; } public function removeCondition(int $index): void { unset($this->form['conditions'][$index]); $this->form['conditions'] = array_values($this->form['conditions']); } public function addAction(): void { $this->form['actions'][] = ['type' => Trigger::ACTION_TYPES[0], 'value' => '', 'recipient' => 'client', 'email_template_id' => '']; } public function removeAction(int $index): void { unset($this->form['actions'][$index]); $this->form['actions'] = array_values($this->form['actions']); } public function moveActionUp(int $index): void { $this->swapFormActions($index, $index - 1); } public function moveActionDown(int $index): void { $this->swapFormActions($index, $index + 1); } protected function swapFormActions(int $a, int $b): void { if ($b < 0 || $b >= count($this->form['actions'])) { return; } [$this->form['actions'][$a], $this->form['actions'][$b]] = [$this->form['actions'][$b], $this->form['actions'][$a]]; } public function submit(): void { $this->validate([ 'form.name' => ['required', 'string', 'max:255'], 'form.event' => ['required', 'string', 'in:'.implode(',', Trigger::EVENTS)], 'form.conditions' => ['array'], 'form.conditions.*.field' => ['required', 'string', 'in:'.implode(',', Trigger::CONDITION_FIELDS)], 'form.conditions.*.operator' => ['required', 'string', 'in:'.implode(',', Trigger::CONDITION_OPERATORS)], 'form.actions' => ['required', 'array', 'min:1'], 'form.actions.*.type' => ['required', 'string', 'in:'.implode(',', Trigger::ACTION_TYPES)], ]); $data = [ 'name' => $this->form['name'], 'enabled' => (bool) $this->form['enabled'], 'event' => $this->form['event'], 'conditions' => array_values($this->form['conditions']), 'actions' => array_values($this->form['actions']), ]; if ($this->editingId) { Trigger::query()->findOrFail($this->editingId)->update($data); } else { $data['sort_order'] = (Trigger::query()->max('sort_order') ?? 0) + 1; Trigger::query()->create($data); } $this->formOpen = false; unset($this->triggers); } public function toggleEnabled(int $id): void { $trigger = Trigger::query()->findOrFail($id); $trigger->update(['enabled' => ! $trigger->enabled]); unset($this->triggers); } public function removeTrigger(int $id): void { Trigger::query()->findOrFail($id)->delete(); unset($this->triggers); } public function moveUp(int $id): void { $this->swapAdjacentSortOrder($id, -1); } public function moveDown(int $id): void { $this->swapAdjacentSortOrder($id, 1); } protected function swapAdjacentSortOrder(int $id, int $direction): void { $ordered = $this->triggers; $index = $ordered->search(fn ($row) => $row->id === $id); $swapIndex = $index + $direction; if ($index === false || $swapIndex < 0 || $swapIndex >= $ordered->count()) { return; } $row = $ordered[$index]; $neighbor = $ordered[$swapIndex]; [$rowOrder, $neighborOrder] = [$row->sort_order, $neighbor->sort_order]; $row->update(['sort_order' => $neighborOrder]); $neighbor->update(['sort_order' => $rowOrder]); unset($this->triggers); } // ===================== TEMPLATES (wyzwalaczy) ===================== public function openTemplateForm(): void { $this->editingTemplateId = null; $this->templateForm = ['name' => '', 'subject' => '', 'body' => '']; $this->resetErrorBag(); $this->templateFormOpen = true; } public function editTemplate(int $id): void { $template = TriggerEmailTemplate::query()->findOrFail($id); $this->editingTemplateId = $template->id; $this->templateForm = [ 'name' => $template->name, 'subject' => $template->subject, 'body' => $template->body, ]; $this->resetErrorBag(); $this->templateFormOpen = true; } public function closeTemplateForm(): void { $this->templateFormOpen = false; } public function setTemplateBodyDraft(string $value): void { $this->templateForm['body'] = $value; } public function submitTemplate(): void { $this->validate([ 'templateForm.name' => ['required', 'string', 'max:255'], 'templateForm.subject' => ['required', 'string', 'max:255'], 'templateForm.body' => ['required', 'string'], ]); if ($this->editingTemplateId) { TriggerEmailTemplate::query()->findOrFail($this->editingTemplateId)->update($this->templateForm); } else { TriggerEmailTemplate::query()->create($this->templateForm); } $this->templateFormOpen = false; unset($this->emailTemplates); } public function removeTemplate(int $id): void { TriggerEmailTemplate::query()->findOrFail($id)->delete(); unset($this->emailTemplates); } public function render() { return view('livewire.admin.triggers'); } }