Files
Virtnet.bond/themes/lucentui/views/tickets/show.blade.php

190 lines
12 KiB
PHP

<div class="container mx-auto px-4 py-8 sm:px-6 lg:px-8">
<h1 class="text-3xl lg:text-4xl font-extrabold text-color-base mt-4 mb-2">
{{ __('ticket.tickets') }}
</h1>
<p class="text-lg text-color-muted font-light max-w-2xl mb-8">
Subject: {{ $ticket->subject }}
</p>
<div class="grid grid-cols-1 md:grid-cols-4 gap-6">
<div class="md:col-span-3 order-2 md:order-1">
<div class="bg-background-secondary/50 border border-neutral p-6 rounded-xl shadow-lg mb-6">
<div class="flex flex-col gap-5 max-h-[60vh] overflow-y-auto pr-4 custom-scrollbar" wire:poll.5s>
@foreach ($ticket->messages()->with('user')->get() as $index => $message)
@php
$isMine = $message->user_id === auth()->id();
$isStaff = ! $isMine && ($message->user->role_id ?? null);
@endphp
<div
class="p-4 rounded-lg w-full max-w-[80%] transition-all duration-200
{{ $isMine ? 'ml-auto bg-primary/15 border border-primary/25' : 'mr-auto glass-panel' }}
{{ $isStaff ? 'border-l-2 border-l-secondary' : '' }}">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-2">
<h3 class="font-semibold text-color-base text-lg">{{ $message->user->name }}</h3>
@if($isStaff)
<span class="text-[10px] uppercase tracking-wider font-bold px-1.5 py-0.5 rounded bg-secondary/15 text-secondary">{{ __('Staff') }}</span>
@endif
</div>
<p class="text-sm text-neutral-400">{{ $message->created_at->diffForHumans() }}</p>
</div>
<div class="mt-2 prose dark:prose-invert max-w-none text-color-base">
{!! Str::markdown(nl2br(e($message->message)), ['allow_unsafe_links' => false]) !!}
</div>
{{-- Display Attachments --}}
@if($message->attachments && count($message->attachments) > 0)
<div class="mt-4 pt-4 border-t border-neutral/20">
<p class="text-sm font-medium text-neutral-400 mb-2">
<x-ri-attachment-2 class="inline size-4 mr-1" />
{{ __('ticket.attachments') ?? 'Attachments' }} ({{ count($message->attachments) }})
</p>
<div class="grid grid-cols-2 sm:grid-cols-3 gap-3">
@foreach($message->attachments as $attachment)
<a href="{{ $attachment['url'] }}" target="_blank" class="group block">
<div class="aspect-square rounded-lg overflow-hidden border border-neutral/30 bg-background/50 hover:border-primary/50 transition-colors">
<img src="{{ $attachment['url'] }}" alt="{{ $attachment['name'] }}" class="w-full h-full object-cover group-hover:scale-105 transition-transform duration-200">
</div>
<p class="mt-1 text-xs text-neutral-400 truncate group-hover:text-primary transition-colors">{{ $attachment['name'] }}</p>
</a>
@endforeach
</div>
</div>
@endif
</div>
@endforeach
</div>
</div>
<div class="bg-background-secondary/70 border border-neutral p-6 rounded-xl shadow-lg mt-6">
<form wire:submit.prevent="save">
<div wire:ignore>
<textarea id="editor" class="form-input h-40"></textarea>
</div>
<x-easymde-editor />
<!-- File Upload Section -->
<div class="mt-4">
<label class="block text-sm font-medium text-color-base mb-2">
<x-ri-attachment-2 class="inline size-4 mr-1" />
{{ __('ticket.attachments') ?? 'Attachments' }}
</label>
<div class="flex items-center justify-center w-full">
<label for="attachments" class="flex flex-col items-center justify-center w-full h-32 border-2 border-neutral border-dashed rounded-lg cursor-pointer bg-background/50 hover:bg-background/80 transition-colors">
<div class="flex flex-col items-center justify-center pt-5 pb-6">
<x-ri-upload-cloud-2-line class="size-8 mb-2 text-neutral-400" />
<p class="mb-2 text-sm text-neutral-400">
<span class="font-semibold">{{ __('ticket.click_to_upload') ?? 'Click to upload' }}</span> {{ __('ticket.or_drag_drop') ?? 'or drag and drop' }}
</p>
<p class="text-xs text-neutral-500">{{ __('ticket.image_formats') ?? 'PNG, JPG, GIF up to 5MB' }}</p>
</div>
<input id="attachments" type="file" class="hidden" wire:model="attachments" multiple accept="image/*" />
</label>
</div>
<!-- Upload Progress -->
<div wire:loading wire:target="attachments" class="mt-2">
<div class="flex items-center gap-2 text-sm text-primary">
<x-ri-loader-4-line class="size-4 animate-spin" />
{{ __('ticket.uploading') ?? 'Uploading...' }}
</div>
</div>
<!-- Preview Uploaded Files -->
@if(count($attachments) > 0)
<div class="mt-4 grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
@foreach($attachments as $index => $attachment)
<div class="relative group">
<div class="aspect-square rounded-lg overflow-hidden border border-neutral bg-background">
<img src="{{ $attachment->temporaryUrl() }}" alt="Preview" class="w-full h-full object-cover">
</div>
<button type="button" wire:click="removeAttachment({{ $index }})"
class="absolute -top-2 -right-2 bg-error text-white rounded-full p-1 opacity-0 group-hover:opacity-100 transition-opacity shadow-lg hover:bg-error/80">
<x-ri-close-line class="size-4" />
</button>
<p class="mt-1 text-xs text-neutral-400 truncate">{{ $attachment->getClientOriginalName() }}</p>
</div>
@endforeach
</div>
@endif
@error('attachments.*')
<p class="mt-2 text-sm text-error">{{ $message }}</p>
@enderror
</div>
<div class="flex justify-end mt-4">
<x-button.primary class="py-3 text-base font-bold transition-all transform rounded-lg shadow-lg hover:bg-primary focus:outline-none focus:ring-4 focus:ring-primary-500 hover:-translate-y-0.5">
{{ __('ticket.reply') }}
</x-button.primary>
</div>
</form>
</div>
</div>
<div class="md:col-span-1 order-1 md:order-2">
<div class="bg-background-secondary/50 border border-neutral p-6 rounded-xl shadow-lg">
<h2 class="text-xl font-bold text-color-base mb-4">{{ __('ticket.ticket_details') }}</h2>
<div class="space-y-4">
{{-- Subject --}}
<div class="flex flex-col">
<span class="text-sm font-medium text-neutral-400">{{ __('ticket.subject') }}:</span>
<span class="text-lg font-semibold text-color-base">{{ $ticket->subject }}</span>
</div>
{{-- Status --}}
<div class="flex flex-col">
<span class="text-sm font-medium text-neutral-400 mb-1">{{ __('ticket.status') }}:</span>
<div class="text-sm font-semibold px-3 py-1 rounded-full w-fit flex items-center gap-1.5
@if ($ticket->status == 'open') text-success bg-success/20
@elseif($ticket->status == 'closed') text-inactive bg-inactive/20
@elseif($ticket->status == 'replied') text-info bg-info/20
@else text-warning bg-warning/20
@endif">
@if ($ticket->status == 'open')
<x-ri-add-circle-fill class="size-4" />
Open
@elseif($ticket->status == 'closed')
<x-ri-forbid-fill class="size-4" />
Closed
@elseif($ticket->status == 'replied')
<x-ri-chat-smile-2-fill class="size-4" />
Replied
@else
<x-ri-error-warning-fill class="size-4" />
{{ ucfirst($ticket->status) }}
@endif
</div>
</div>
<div class="flex flex-col">
<span class="text-sm font-medium text-neutral-400">{{ __('ticket.priority') }}:</span>
<span class="text-base text-color-base">{{ ucfirst($ticket->priority) }}</span>
</div>
<div class="flex flex-col">
<span class="text-sm font-medium text-neutral-400">{{ __('ticket.created_at') }}:</span>
<span class="text-base text-color-base">{{ $ticket->created_at->format('d M Y, H:i') }} ({{ $ticket->created_at->diffForHumans() }})</span>
</div>
@if ($ticket->department)
<div class="flex flex-col">
<span class="text-sm font-medium text-neutral-400">{{ __('ticket.department') }}:</span>
<span class="text-base text-color-base">{{ $ticket->department }}</span>
</div>
@endif
@if ($ticket->service)
<div class="flex flex-col">
<span class="text-sm font-medium text-neutral-400">{{ __('ticket.service') }}:</span>
<span class="text-base text-color-base">
<a href="{{ route('services.show', $ticket->service) }}" class="text-primary font-bold hover:underline" wire:navigate>
{{ $ticket->service->product->name }}
</a>
</span>
</div>
@endif
</div>
</div>
</div>
</div>
</div>