feat(tickets): desktop mobile-upload UX, max10 files, attachment cues
This commit is contained in:
parent
2b7dcb6ab7
commit
62f8613f9e
|
|
@ -387,7 +387,8 @@ private function loadTickets(): void
|
|||
}
|
||||
|
||||
$query = Ticket::query()
|
||||
->with(['categoriaTicket', 'assegnatoAFornitore:id,ragione_sociale,nome,cognome'])
|
||||
->with(['categoriaTicket', 'assegnatoAFornitore:id,ragione_sociale,nome,cognome', 'assegnatoAUser:id,name'])
|
||||
->withCount('attachments')
|
||||
->where('stabile_id', $stabileId);
|
||||
|
||||
if ($this->status === 'open') {
|
||||
|
|
|
|||
|
|
@ -290,21 +290,32 @@ public function selezionaCaller(int $rubricaId): void
|
|||
public function creaTicketRapido(): void
|
||||
{
|
||||
$this->validate([
|
||||
'newTicketTitolo' => ['required', 'string', 'max:255'],
|
||||
'newTicketDescrizione' => ['required', 'string'],
|
||||
'newTicketLuogo' => ['nullable', 'string', 'max:255'],
|
||||
'newTicketPriorita' => ['required', 'in:Bassa,Media,Alta,Urgente'],
|
||||
'newTicketCategoriaId' => ['nullable', 'integer', 'exists:categorie_ticket,id'],
|
||||
'newTicketTipoIntervento' => ['nullable', 'string', 'max:80'],
|
||||
'newTicketFotoNote' => ['nullable', 'string', 'max:2000'],
|
||||
'newTicketCameraShots' => ['nullable', 'array', 'max:8'],
|
||||
'newTicketCameraShots.*' => ['file', 'max:10240', 'mimes:jpg,jpeg,png,webp'],
|
||||
'newTicketAttachments' => ['nullable', 'array', 'max:8'],
|
||||
'newTicketAttachments.*' => ['file', 'max:10240', 'mimes:jpg,jpeg,png,webp,pdf,doc,docx,xls,xlsx,txt'],
|
||||
'newTicketTitolo' => ['required', 'string', 'max:255'],
|
||||
'newTicketDescrizione' => ['required', 'string'],
|
||||
'newTicketLuogo' => ['nullable', 'string', 'max:255'],
|
||||
'newTicketPriorita' => ['required', 'in:Bassa,Media,Alta,Urgente'],
|
||||
'newTicketCategoriaId' => ['nullable', 'integer', 'exists:categorie_ticket,id'],
|
||||
'newTicketTipoIntervento' => ['nullable', 'string', 'max:80'],
|
||||
'newTicketFotoNote' => ['nullable', 'string', 'max:2000'],
|
||||
'newTicketCameraShots' => ['nullable', 'array', 'max:10'],
|
||||
'newTicketCameraShots.*' => ['file', 'max:10240', 'mimes:jpg,jpeg,png,webp'],
|
||||
'newTicketAttachments' => ['nullable', 'array', 'max:10'],
|
||||
'newTicketAttachments.*' => ['file', 'max:10240', 'mimes:jpg,jpeg,png,webp,pdf,doc,docx,xls,xlsx,txt'],
|
||||
'newTicketAttachmentDescriptions' => ['nullable', 'array'],
|
||||
'newTicketAttachmentDescriptions.*' => ['nullable', 'string', 'max:255'],
|
||||
]);
|
||||
|
||||
$totalUploads = count($this->newTicketCameraShots) + count($this->newTicketAttachments);
|
||||
if ($totalUploads > 10) {
|
||||
Notification::make()
|
||||
->title('Troppi allegati selezionati')
|
||||
->body('Puoi caricare al massimo 10 file totali (foto + documenti) per ticket.')
|
||||
->warning()
|
||||
->send();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
if (! $user instanceof User) {
|
||||
return;
|
||||
|
|
@ -375,16 +386,16 @@ public function creaTicketRapido(): void
|
|||
->success()
|
||||
->send();
|
||||
|
||||
$this->newTicketTitolo = null;
|
||||
$this->newTicketDescrizione = null;
|
||||
$this->newTicketLuogo = null;
|
||||
$this->newTicketPriorita = 'Media';
|
||||
$this->newTicketCategoriaId = null;
|
||||
$this->newTicketTipoIntervento = 'altro';
|
||||
$this->newTicketCameraShots = [];
|
||||
$this->newTicketAttachments = [];
|
||||
$this->newTicketTitolo = null;
|
||||
$this->newTicketDescrizione = null;
|
||||
$this->newTicketLuogo = null;
|
||||
$this->newTicketPriorita = 'Media';
|
||||
$this->newTicketCategoriaId = null;
|
||||
$this->newTicketTipoIntervento = 'altro';
|
||||
$this->newTicketCameraShots = [];
|
||||
$this->newTicketAttachments = [];
|
||||
$this->newTicketAttachmentDescriptions = [];
|
||||
$this->newTicketFotoNote = null;
|
||||
$this->newTicketFotoNote = null;
|
||||
$this->refreshData();
|
||||
}
|
||||
|
||||
|
|
@ -419,7 +430,7 @@ public function removeNewTicketFile(int $index): void
|
|||
*/
|
||||
public function getSelectedUploadsProperty(): array
|
||||
{
|
||||
$rows = [];
|
||||
$rows = [];
|
||||
$files = array_merge($this->newTicketCameraShots, $this->newTicketAttachments);
|
||||
|
||||
foreach ($files as $index => $file) {
|
||||
|
|
@ -427,8 +438,8 @@ public function getSelectedUploadsProperty(): array
|
|||
continue;
|
||||
}
|
||||
|
||||
$name = (string) (method_exists($file, 'getClientOriginalName') ? $file->getClientOriginalName() : ('file-' . $index));
|
||||
$mime = (string) (method_exists($file, 'getClientMimeType') ? $file->getClientMimeType() : 'application/octet-stream');
|
||||
$name = (string) (method_exists($file, 'getClientOriginalName') ? $file->getClientOriginalName() : ('file-' . $index));
|
||||
$mime = (string) (method_exists($file, 'getClientMimeType') ? $file->getClientMimeType() : 'application/octet-stream');
|
||||
$isImage = str_starts_with($mime, 'image/');
|
||||
|
||||
$previewUrl = null;
|
||||
|
|
@ -510,7 +521,7 @@ private function salvaAllegatiTicket(Ticket $ticket, int $userId): int
|
|||
private function syncAttachmentDescriptionSlots(): void
|
||||
{
|
||||
$files = array_merge($this->newTicketCameraShots, $this->newTicketAttachments);
|
||||
$next = [];
|
||||
$next = [];
|
||||
|
||||
foreach ($files as $index => $_file) {
|
||||
$next[$index] = (string) ($this->newTicketAttachmentDescriptions[$index] ?? '');
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
<th class="border px-2 py-2 text-left">ID</th>
|
||||
<th class="border px-2 py-2 text-left">Titolo</th>
|
||||
<th class="border px-2 py-2 text-left">Categoria</th>
|
||||
<th class="border px-2 py-2 text-left">Assegnato a</th>
|
||||
<th class="border px-2 py-2 text-left">Priorita</th>
|
||||
<th class="border px-2 py-2 text-left">Stato</th>
|
||||
<th class="border px-2 py-2 text-left">Apertura</th>
|
||||
|
|
@ -50,8 +51,18 @@
|
|||
@forelse($tickets as $ticket)
|
||||
<tr id="ticket-{{ (int) $ticket->id }}" class="hover:bg-slate-50">
|
||||
<td class="border px-2 py-2">#{{ (int) $ticket->id }}</td>
|
||||
<td class="border px-2 py-2">{{ $ticket->titolo }}</td>
|
||||
<td class="border px-2 py-2">
|
||||
<div class="flex items-center gap-1">
|
||||
<span>{{ $ticket->titolo }}</span>
|
||||
@if(((int) ($ticket->attachments_count ?? 0)) > 0)
|
||||
<span title="Presenza allegati" class="inline-flex items-center rounded bg-emerald-100 px-1.5 py-0.5 text-[10px] font-semibold text-emerald-800">
|
||||
ATT {{ (int) $ticket->attachments_count }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
<td class="border px-2 py-2">{{ optional($ticket->categoriaTicket)->nome ?: '-' }}</td>
|
||||
<td class="border px-2 py-2">{{ optional($ticket->assegnatoAUser)->name ?: '-' }}</td>
|
||||
<td class="border px-2 py-2">{{ $ticket->priorita }}</td>
|
||||
<td class="border px-2 py-2">{{ $ticket->stato }}</td>
|
||||
<td class="border px-2 py-2">{{ optional($ticket->data_apertura)->format('d/m/Y H:i') }}</td>
|
||||
|
|
@ -80,7 +91,7 @@
|
|||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7" class="border px-2 py-4 text-center text-gray-500">Nessun ticket per il filtro selezionato.</td>
|
||||
<td colspan="8" class="border px-2 py-4 text-center text-gray-500">Nessun ticket per il filtro selezionato.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
|
|
|
|||
|
|
@ -140,10 +140,11 @@
|
|||
|
||||
<label class="inline-flex cursor-pointer items-center rounded-md bg-indigo-600 px-3 py-2 text-xs font-medium text-white hover:bg-indigo-500">
|
||||
Aggiungi allegati
|
||||
<input type="file" wire:model="newTicketAttachments" multiple accept="image/*,.pdf,.doc,.docx,.xls,.xlsx,.txt" class="hidden" />
|
||||
<input type="file" wire:model="newTicketAttachments" multiple accept=".pdf,.doc,.docx,.xls,.xlsx,.txt,image/*" class="hidden" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="mt-1 text-xs text-gray-500">Dopo ogni scatto puoi aggiungere subito la descrizione. Se servono altre foto usa di nuovo "Scatta foto".</div>
|
||||
<div class="mt-1 text-xs text-gray-500">Puoi caricare fino a 10 file totali (foto + documenti). Ogni file ha descrizione separata.</div>
|
||||
<div class="mt-1 text-xs text-gray-500">iPhone: su "Aggiungi allegati" scegli "Sfoglia" per aprire l'app File (iCloud Drive/On My iPhone).</div>
|
||||
</label>
|
||||
|
||||
@if(count($this->selectedUploads) > 0)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user