v1.0.0
This commit is contained in:
401
src/resources/views/livewire/operator/ticket-show.blade.php
Normal file
401
src/resources/views/livewire/operator/ticket-show.blade.php
Normal file
@@ -0,0 +1,401 @@
|
||||
<div style="flex:1;display:flex;flex-direction:column">
|
||||
<x-topbar />
|
||||
|
||||
<div class="page-pad" style="flex:1;padding:20px 24px;overflow:auto">
|
||||
<div style="display:flex;flex-direction:column;gap:16px;max-width:1020px;margin:0 auto">
|
||||
<a href="{{ route('operator.queue') }}" wire:navigate class="btn btn-ghost" style="align-self:flex-start;padding:0">← Wróć do listy</a>
|
||||
|
||||
<div style="display:flex;gap:20px;align-items:flex-start;flex-wrap:wrap">
|
||||
<div class="main-col" style="display:flex;flex-direction:column;gap:16px">
|
||||
<div class="card" style="padding:20px;gap:8px">
|
||||
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:8px">
|
||||
<div class="card-kicker">Zgłoszenie #{{ $ticket->number }}</div>
|
||||
@unless ($editingDetails)
|
||||
<button type="button" class="btn btn-ghost" style="padding:0" wire:click="toggleEditDetails">Edytuj</button>
|
||||
@endunless
|
||||
</div>
|
||||
|
||||
@unless ($editingDetails)
|
||||
<h3 style="margin:2px 0 0">{{ $ticket->subject }}</h3>
|
||||
<div class="card-meta">{{ $ticket->categoryLabel() }}</div>
|
||||
<div style="white-space:pre-wrap;font-size:14px;margin-top:4px">{{ $ticket->body }}</div>
|
||||
@foreach ($this->publicMessages->first()?->attachments ?? [] as $a)
|
||||
<x-message-attachment :attachment="$a" />
|
||||
@endforeach
|
||||
@if (count($ticket->customFieldEntries()))
|
||||
<div style="display:flex;flex-direction:column;gap:2px;margin-top:2px">
|
||||
@foreach ($ticket->customFieldEntries() as $cf)
|
||||
<div style="font-size:14px"><strong>{{ $cf['label'] }}:</strong> {{ $cf['value'] }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<div class="field"><label>Temat</label><input class="input" wire:model="editDetailsForm.subject"></div>
|
||||
<div class="field"><label>Treść</label><textarea class="input" wire:model="editDetailsForm.body"></textarea></div>
|
||||
<div style="display:flex;gap:10px">
|
||||
<div class="field" style="flex:1">
|
||||
<label>Kategoria</label>
|
||||
<select class="input" wire:model.live="editDetailsForm.categoryId">
|
||||
<option value="">Wybierz</option>
|
||||
@foreach ($this->categories as $c)
|
||||
<option value="{{ $c->id }}">{{ $c->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="field" style="flex:1">
|
||||
<label>Podkategoria</label>
|
||||
<select class="input" wire:model.live="editDetailsForm.subcategoryId" @disabled(! $editDetailsForm['categoryId'])>
|
||||
<option value="">Wybierz</option>
|
||||
@foreach ($this->editDetailsSubcategoryOptions as $s)
|
||||
<option value="{{ $s->id }}">{{ $s->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@foreach ($this->editDetailsSelectedSubcategory?->customFields ?? [] as $field)
|
||||
<x-custom-field-input :field="$field" wire-model="editDetailsForm.customValues" />
|
||||
@endforeach
|
||||
|
||||
<div style="display:flex;gap:8px;margin-top:6px">
|
||||
<button type="button" class="btn btn-secondary" wire:click="cancelEditDetails">Anuluj</button>
|
||||
<button type="button" class="btn btn-primary" wire:click="saveDetails">Zapisz</button>
|
||||
</div>
|
||||
@endunless
|
||||
</div>
|
||||
|
||||
<div class="card" style="padding:16px;gap:10px">
|
||||
<div class="card-kicker">Notatki wewnętrzne</div>
|
||||
@forelse ($this->internalMessages as $m)
|
||||
<div style="padding:10px 12px;border-left:3px solid var(--color-accent);background:var(--color-surface);border-radius:4px">
|
||||
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:8px">
|
||||
<div style="font-size:11px;opacity:0.65;margin-bottom:4px">{{ $m->author_name }} · {{ \App\Support\Rel::format($m->created_at) }}</div>
|
||||
@if ($m->role === 'operator')
|
||||
<div style="display:flex;gap:6px;flex:none">
|
||||
<span class="material-symbols-outlined" style="font-size:16px;cursor:pointer;opacity:0.7" wire:click="startEditNote({{ $m->id }}, @js($m->body))">edit</span>
|
||||
<span class="material-symbols-outlined" style="font-size:16px;cursor:pointer;opacity:0.7" wire:click="requestDeleteMessage({{ $m->id }})">delete</span>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@if ($editingNoteId === $m->id)
|
||||
<textarea class="input" wire:model="editingNoteDraft"></textarea>
|
||||
<div style="display:flex;gap:8px;margin-top:6px">
|
||||
<button type="button" class="btn btn-secondary" wire:click="cancelEditNote">Anuluj</button>
|
||||
<button type="button" class="btn btn-primary" wire:click="saveEditNote">Zapisz</button>
|
||||
</div>
|
||||
@else
|
||||
<div style="white-space:pre-wrap">{{ $m->body }}</div>
|
||||
@endif
|
||||
@foreach ($m->attachments as $a)
|
||||
<x-message-attachment :attachment="$a" />
|
||||
@endforeach
|
||||
</div>
|
||||
@empty
|
||||
<p class="text-muted" style="font-size:13px;margin:0">Brak notatek wewnętrznych.</p>
|
||||
@endforelse
|
||||
@if ($addingNote)
|
||||
<textarea class="input" placeholder="Dodaj notatkę widoczną tylko dla zespołu…" wire:model="noteDraft"></textarea>
|
||||
<div style="display:flex;align-items:center;gap:10px">
|
||||
<div style="flex:1;min-width:0;border:1px dashed var(--color-divider);border-radius:8px;padding:10px 14px;display:flex;flex-wrap:wrap;align-items:center;gap:10px">
|
||||
<label class="btn btn-secondary" style="cursor:pointer;flex:none">Załącz pliki<input type="file" multiple style="display:none" wire:model="noteAttachments"></label>
|
||||
@forelse ($noteAttachments as $i => $file)
|
||||
<span class="text-muted" style="font-size:13px;display:flex;align-items:center;gap:6px;min-width:0">
|
||||
<span class="material-symbols-outlined" style="font-size:16px;flex:none">attach_file</span>
|
||||
<span style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{ $file->getClientOriginalName() }}</span>
|
||||
<span class="material-symbols-outlined" style="font-size:16px;cursor:pointer;opacity:0.7;flex:none" wire:click="removeNoteAttachment({{ $i }})">close</span>
|
||||
</span>
|
||||
@empty
|
||||
<span class="text-muted" style="font-size:13px">Brak załączników</span>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
@error('noteAttachments') <span style="color:var(--color-danger);font-size:12px">{{ $message }}</span> @enderror
|
||||
<div style="display:flex;gap:8px">
|
||||
<button type="button" class="btn btn-secondary" wire:click="cancelAddNote">Anuluj</button>
|
||||
<button type="button" class="btn btn-primary" wire:click="addNote">Dodaj notatkę</button>
|
||||
</div>
|
||||
@else
|
||||
<button type="button" class="btn btn-secondary" wire:click="startAddNote">Dodaj notatkę</button>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@php $threadMessages = $this->publicMessages->skip(1); @endphp
|
||||
<div style="display:flex;flex-direction:column;gap:10px">
|
||||
@foreach ($threadMessages as $m)
|
||||
@php $mine = $m->role === 'operator'; @endphp
|
||||
<div style="display:flex;justify-content:{{ $mine ? 'flex-end' : 'flex-start' }}">
|
||||
<div style="max-width:75%;padding:10px 14px;border-radius:12px;font-size:14px;background:{{ $mine ? 'var(--color-accent-800)' : 'var(--color-surface)' }};color:{{ $mine ? 'var(--color-accent-100)' : 'var(--color-text)' }};border:1px solid var(--color-divider)">
|
||||
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:10px">
|
||||
<div style="font-size:11px;opacity:0.65;margin-bottom:4px">{{ $m->author_name }} · {{ \App\Support\Rel::format($m->created_at) }}{{ $m->edited ? ' · edytowano' : '' }}</div>
|
||||
@if ($m->role === 'operator')
|
||||
<div style="display:flex;gap:6px;flex:none">
|
||||
<span class="material-symbols-outlined" style="font-size:15px;cursor:pointer;opacity:0.7" wire:click="startEditMessage({{ $m->id }}, @js($m->body))">edit</span>
|
||||
<span class="material-symbols-outlined" style="font-size:15px;cursor:pointer;opacity:0.7" wire:click="requestDeleteMessage({{ $m->id }})">delete</span>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@if ($editingMessageId === $m->id)
|
||||
<textarea class="input" wire:model="editingMessageDraft"></textarea>
|
||||
<div style="display:flex;gap:8px;margin-top:6px">
|
||||
<button type="button" class="btn btn-secondary" wire:click="cancelEditMessage">Anuluj</button>
|
||||
<button type="button" class="btn btn-primary" wire:click="saveEditMessage">Zapisz</button>
|
||||
</div>
|
||||
@else
|
||||
<div style="white-space:pre-wrap">{{ $m->body }}</div>
|
||||
@endif
|
||||
@foreach ($m->attachments as $a)
|
||||
<x-message-attachment :attachment="$a" />
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<form wire:submit="sendReply" class="card" style="padding:16px;gap:10px">
|
||||
<select class="input" wire:change="setTemplate($event.target.value)">
|
||||
<option value="">Wstaw szablon odpowiedzi…</option>
|
||||
@foreach ($this->responseTemplates as $rt)
|
||||
<option value="{{ $rt->id }}" @selected($templateId === (string) $rt->id)>{{ $rt->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<textarea class="input" placeholder="Napisz odpowiedź do klienta…" wire:model="reply"></textarea>
|
||||
<div style="display:flex;align-items:center;gap:10px">
|
||||
<div style="flex:1;min-width:0;border:1px dashed var(--color-divider);border-radius:8px;padding:10px 14px;display:flex;flex-wrap:wrap;align-items:center;gap:10px">
|
||||
<label class="btn btn-secondary" style="cursor:pointer;flex:none">Załącz pliki<input type="file" multiple style="display:none" wire:model="replyAttachments"></label>
|
||||
@forelse ($replyAttachments as $i => $file)
|
||||
<span class="text-muted" style="font-size:13px;display:flex;align-items:center;gap:6px;min-width:0">
|
||||
<span class="material-symbols-outlined" style="font-size:16px;flex:none">attach_file</span>
|
||||
<span style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{ $file->getClientOriginalName() }}</span>
|
||||
<span class="material-symbols-outlined" style="font-size:16px;cursor:pointer;opacity:0.7;flex:none" wire:click="removeReplyAttachment({{ $i }})">close</span>
|
||||
</span>
|
||||
@empty
|
||||
<span class="text-muted" style="font-size:13px">Brak załączników</span>
|
||||
@endforelse
|
||||
</div>
|
||||
<div style="display:flex;position:relative;flex:none" x-data="{ open: false }" @click.outside="open = false">
|
||||
<button class="btn btn-primary" style="border-top-right-radius:0;border-bottom-right-radius:0" type="submit">Wyślij odpowiedź</button>
|
||||
<button class="btn btn-primary" type="button" style="border-top-left-radius:0;border-bottom-left-radius:0;border-left:1px solid var(--color-bg);padding:0 6px" @click="open = !open">
|
||||
<span class="material-symbols-outlined" style="font-size:16px">expand_more</span>
|
||||
</button>
|
||||
<div x-show="open" x-cloak style="position:absolute;bottom:100%;right:0;margin-bottom:6px;background:var(--color-surface);border:1px solid var(--color-divider);border-radius:8px;box-shadow:var(--shadow-md);min-width:220px;overflow:hidden;z-index:10">
|
||||
@forelse ($this->replyQuickActions as $qa)
|
||||
<button type="button" class="theme-toggle-option" @click="open = false" wire:click="sendAndTransition({{ $qa->id }})">{{ $qa->label }}</button>
|
||||
@empty
|
||||
<div class="text-muted" style="font-size:12.5px;padding:8px 12px">Brak skonfigurowanych szybkich akcji.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@error('replyAttachments') <span style="color:var(--color-danger);font-size:12px">{{ $message }}</span> @enderror
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="aside-col" style="display:flex;flex-direction:column;gap:14px">
|
||||
<div class="card" style="padding:16px;gap:6px">
|
||||
<div style="display:flex;justify-content:space-between;align-items:flex-start;gap:8px">
|
||||
<div class="card-kicker">Zgłaszający</div>
|
||||
<span class="material-symbols-outlined" style="font-size:16px;cursor:pointer;opacity:0.7" wire:click="startEditReporter">edit</span>
|
||||
</div>
|
||||
<div style="font-weight:500">{{ $ticket->name }}</div>
|
||||
<div class="text-muted" style="font-size:13px">{{ $ticket->email }}</div>
|
||||
@if ($ticket->customer_id)
|
||||
<a href="{{ route('operator.queue', ['filterCustomerId' => $ticket->customer_id]) }}" wire:navigate class="text-muted" style="font-size:12px;color:var(--color-accent);text-decoration:none">Zobacz zgłoszenia tej osoby →</a>
|
||||
@php $reporterFields = $ticket->customer?->customFieldEntries() ?? []; @endphp
|
||||
@if (count($reporterFields))
|
||||
<div style="display:flex;flex-direction:column;gap:2px;margin-top:6px;padding-top:8px;border-top:1px solid var(--color-divider)">
|
||||
@foreach ($reporterFields as $cf)
|
||||
<div class="card-meta"><strong>{{ $cf['label'] }}:</strong> {{ $cf['value'] }}</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($editingReporter)
|
||||
<div class="card" style="padding:16px;gap:10px">
|
||||
<div class="field">
|
||||
<label>Zmień zgłaszającego</label>
|
||||
<select class="input" wire:model="editReporterCustomerId">
|
||||
<option value="">Wybierz klienta</option>
|
||||
@foreach ($this->clients as $cl)
|
||||
<option value="{{ $cl->id }}">{{ $cl->name }} — {{ $cl->email }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px">
|
||||
<button type="button" class="btn btn-secondary" wire:click="cancelEditReporter">Anuluj</button>
|
||||
<button type="button" class="btn btn-primary" wire:click="saveReporter">Zapisz</button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="card" style="padding:16px;gap:10px">
|
||||
<div class="card-kicker">Status i przypisanie</div>
|
||||
<div class="field">
|
||||
<label>Status</label>
|
||||
<select class="input" wire:change="setStatus($event.target.value)">
|
||||
@foreach ($this->statuses as $s)
|
||||
<option value="{{ $s->key }}" @selected($ticket->status_key === $s->key)>{{ $s->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Priorytet</label>
|
||||
<select class="input" wire:change="setPriority($event.target.value)">
|
||||
@foreach ($this->priorities as $p)
|
||||
<option value="{{ $p->key }}" @selected($ticket->priority_key === $p->key)>{{ $p->label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Zespół</label>
|
||||
<select class="input" wire:change="setTeam($event.target.value)">
|
||||
<option value="">Brak</option>
|
||||
@foreach ($this->teams as $tm)
|
||||
<option value="{{ $tm->id }}" @selected($ticket->team_id === $tm->id)>{{ $tm->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Przypisany do</label>
|
||||
<div style="display:flex;gap:6px">
|
||||
<select class="input" wire:change="setAssignee($event.target.value)" style="flex:1">
|
||||
<option value="">Nieprzypisane</option>
|
||||
@foreach ($this->operators as $o)
|
||||
<option value="{{ $o->id }}" @selected($ticket->assignee_id === $o->id)>{{ $o->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@if ($ticket->assignee_id !== auth()->id())
|
||||
<button type="button" class="btn btn-secondary" style="flex:none" wire:click="assignToMe">Przypisz do mnie</button>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="padding:16px;gap:8px">
|
||||
<div class="card-kicker">SLA</div>
|
||||
<div style="font-size:12.5px">{{ $ticket->slaInfo()['text'] }}</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="padding:16px;gap:8px">
|
||||
<div class="card-kicker">MONITOR CZASU PRACY</div>
|
||||
<div
|
||||
style="display:flex;flex-direction:column;gap:6px"
|
||||
x-data="{
|
||||
seconds: {{ $ticket->timerElapsedSeconds() }},
|
||||
running: @js((bool) $ticket->timer_started_at),
|
||||
tick: null,
|
||||
navigatingHandler: null,
|
||||
pagehideHandler: null,
|
||||
format() {
|
||||
const h = Math.floor(this.seconds / 3600);
|
||||
const m = Math.floor((this.seconds % 3600) / 60);
|
||||
const s = this.seconds % 60;
|
||||
return [h, m, s].map(n => String(n).padStart(2, '0')).join(':');
|
||||
},
|
||||
start() {
|
||||
clearInterval(this.tick);
|
||||
if (this.running) {
|
||||
this.tick = setInterval(() => { this.seconds++ }, 1000);
|
||||
}
|
||||
},
|
||||
init() {
|
||||
this.start();
|
||||
|
||||
// The timer only tracks time this ticket is actually open in
|
||||
// the browser: stop it server-side the moment the operator
|
||||
// navigates elsewhere in the app (wire:navigate — a normal
|
||||
// Livewire call, since the document itself isn't unloading)…
|
||||
this.navigatingHandler = () => {
|
||||
if (this.running) $wire.call('stopTimer');
|
||||
};
|
||||
document.addEventListener('livewire:navigating', this.navigatingHandler);
|
||||
|
||||
// …or closes/reloads the tab. Regular fetch/Livewire calls
|
||||
// can get cut off mid-flight during an actual page unload, so
|
||||
// this uses sendBeacon against a plain endpoint instead, which
|
||||
// browsers guarantee to deliver.
|
||||
this.pagehideHandler = () => {
|
||||
if (this.running) {
|
||||
navigator.sendBeacon(@js(route('operator.ticket.stop-timer', $ticket)));
|
||||
}
|
||||
};
|
||||
window.addEventListener('pagehide', this.pagehideHandler);
|
||||
},
|
||||
destroy() {
|
||||
clearInterval(this.tick);
|
||||
document.removeEventListener('livewire:navigating', this.navigatingHandler);
|
||||
window.removeEventListener('pagehide', this.pagehideHandler);
|
||||
},
|
||||
}"
|
||||
>
|
||||
@if ($editingTimer)
|
||||
<div style="display:flex;align-items:center;gap:4px;font-size:12px">
|
||||
<input class="input" type="number" min="0" style="width:60px" wire:model="editTimerHours"> godz.
|
||||
<input class="input" type="number" min="0" max="59" style="width:52px" wire:model="editTimerMinutes"> min.
|
||||
<input class="input" type="number" min="0" max="59" style="width:52px" wire:model="editTimerSeconds"> sek.
|
||||
</div>
|
||||
<div style="display:flex;gap:6px">
|
||||
<button type="button" class="btn btn-secondary" wire:click="cancelEditTimer">Anuluj</button>
|
||||
<button type="button" class="btn btn-primary" wire:click="saveEditTimer">Zapisz</button>
|
||||
</div>
|
||||
@else
|
||||
<div style="font-size:12px;display:flex;align-items:center;gap:6px">
|
||||
<span>Czas w zgłoszeniu: <strong x-text="format()"></strong></span>
|
||||
<span class="material-symbols-outlined" style="font-size:16px;cursor:pointer;opacity:0.7" wire:click="startEditTimer">edit</span>
|
||||
</div>
|
||||
<div style="display:flex;gap:6px">
|
||||
@if ($ticket->timer_started_at)
|
||||
<button type="button" class="btn btn-secondary" wire:click="stopTimer" @click="running = false; clearInterval(tick)">Zatrzymaj</button>
|
||||
@else
|
||||
<button type="button" class="btn btn-secondary" wire:click="resumeTimer" @click="running = true; start()">Wznów</button>
|
||||
@endif
|
||||
<button type="button" class="btn btn-secondary" wire:click="resetTimer" @click="seconds = 0; running = false; clearInterval(tick)">Resetuj</button>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="padding:16px;gap:8px">
|
||||
<div class="card-kicker">Historia zmian</div>
|
||||
@forelse ($ticket->histories as $h)
|
||||
<div style="font-size:12.5px"><span>{{ $h->text }}</span><div class="text-muted" style="font-size:11px">{{ \App\Support\Rel::format($h->created_at) }}</div></div>
|
||||
@empty
|
||||
<p class="text-muted" style="font-size:12px;margin:0">Brak historii zmian.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
<div class="card" style="padding:16px;gap:8px">
|
||||
<button type="button" class="btn btn-secondary btn-block" wire:click="requestDeleteTicket">Usuń zgłoszenie</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if ($pendingDeleteMessageId)
|
||||
<div class="dialog-backdrop">
|
||||
<div class="dialog" style="max-width:400px">
|
||||
<div class="dialog-title">Potwierdź usunięcie</div>
|
||||
<div class="dialog-body">Czy na pewno usunąć tę wiadomość?</div>
|
||||
<div class="dialog-actions">
|
||||
<button type="button" class="btn btn-secondary" wire:click="cancelDeleteMessage">Anuluj</button>
|
||||
<button type="button" class="btn btn-primary" wire:click="confirmDeleteMessage">Usuń</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($pendingDeleteTicket)
|
||||
<div class="dialog-backdrop">
|
||||
<div class="dialog" style="max-width:400px">
|
||||
<div class="dialog-title">Potwierdź usunięcie</div>
|
||||
<div class="dialog-body">Czy na pewno usunąć zgłoszenie #{{ $ticket->number }}?</div>
|
||||
<div class="dialog-actions">
|
||||
<button type="button" class="btn btn-secondary" wire:click="cancelDeleteTicket">Anuluj</button>
|
||||
<button type="button" class="btn btn-primary" wire:click="confirmDeleteTicket">Usuń</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
Reference in New Issue
Block a user