Files
2026-03-21 15:25:05 +02:00

156 lines
10 KiB
PHP

<x-app-layout>
@php
$currentProject = $project;
@endphp
<x-slot name="header">
<div class="flex items-center justify-between">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">{{ $project->name }} &mdash; Issues</h2>
</div>
</x-slot>
<div class="py-8" x-data="{ selected: [], selectAll: false }">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8 space-y-4">
@if(session('status'))
<div class="bg-green-50 border border-green-200 text-green-700 px-4 py-3 rounded-md text-sm">
{{ session('status') }}
</div>
@endif
{{-- Filters --}}
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg p-4">
<form method="GET" action="{{ route('projects.issues.index', $project) }}" class="flex flex-wrap items-end gap-4">
<div class="flex-1 min-w-[200px]">
<x-input-label for="search" value="Search" />
<x-text-input id="search" name="search" type="text" class="mt-1 block w-full" :value="$search" placeholder="Search issues..." />
</div>
<div>
<x-input-label for="status" value="Status" />
<select id="status" name="status" class="mt-1 block w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm text-sm">
<option value="">All</option>
@foreach(['unresolved', 'resolved', 'ignored', 'muted'] as $s)
<option value="{{ $s }}" {{ $currentStatus === $s ? 'selected' : '' }}>{{ ucfirst($s) }}</option>
@endforeach
</select>
</div>
<div>
<x-input-label for="level" value="Level" />
<select id="level" name="level" class="mt-1 block w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm text-sm">
<option value="">All</option>
@foreach(['fatal', 'error', 'warning', 'info', 'debug'] as $l)
<option value="{{ $l }}" {{ $currentLevel === $l ? 'selected' : '' }}>{{ ucfirst($l) }}</option>
@endforeach
</select>
</div>
@if($environments->isNotEmpty())
<div>
<x-input-label for="environment" value="Environment" />
<select id="environment" name="environment" class="mt-1 block w-full border-gray-300 focus:border-indigo-500 focus:ring-indigo-500 rounded-md shadow-sm text-sm">
<option value="">All</option>
@foreach($environments as $env)
<option value="{{ $env }}" {{ $currentEnvironment === $env ? 'selected' : '' }}>{{ ucfirst($env) }}</option>
@endforeach
</select>
</div>
@endif
<x-primary-button>Filter</x-primary-button>
@if($search || $currentLevel || $currentEnvironment || $currentStatus !== 'unresolved')
<a href="{{ route('projects.issues.index', $project) }}" class="text-sm text-gray-500 hover:text-gray-700">Reset</a>
@endif
</form>
</div>
{{-- Bulk Actions --}}
<div x-show="selected.length > 0" x-cloak class="bg-indigo-50 border border-indigo-200 rounded-md p-3 flex items-center gap-4">
<span class="text-sm font-medium text-indigo-800" x-text="selected.length + ' selected'"></span>
<form method="POST" action="{{ route('projects.issues.bulk', $project) }}" class="flex gap-2">
@csrf
<template x-for="id in selected" :key="id">
<input type="hidden" name="issues[]" :value="id">
</template>
<button type="submit" name="action" value="resolve" class="px-3 py-1 text-xs font-medium rounded-md bg-green-100 text-green-800 hover:bg-green-200 transition">Resolve</button>
<button type="submit" name="action" value="ignore" class="px-3 py-1 text-xs font-medium rounded-md bg-yellow-100 text-yellow-800 hover:bg-yellow-200 transition">Ignore</button>
<button type="submit" name="action" value="mute" class="px-3 py-1 text-xs font-medium rounded-md bg-gray-100 text-gray-800 hover:bg-gray-200 transition">Mute</button>
<button type="submit" name="action" value="delete" class="px-3 py-1 text-xs font-medium rounded-md bg-red-100 text-red-800 hover:bg-red-200 transition"
onclick="return confirm('Delete selected issues permanently?')">Delete</button>
</form>
</div>
{{-- Issues Table --}}
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
@if($issues->isEmpty())
<div class="p-12 text-center text-gray-500">
No issues found.
</div>
@else
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-4 py-3 w-10">
<input type="checkbox" x-model="selectAll"
@change="selectAll ? selected = {{ json_encode($issues->pluck('id')) }} : selected = []"
class="rounded border-gray-300 text-indigo-600 focus:ring-indigo-500">
</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase w-20">Status</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Issue</th>
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase w-24">Events</th>
<th class="px-4 py-3 text-right text-xs font-medium text-gray-500 uppercase w-40">Last Seen</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
@foreach($issues as $issue)
<tr class="hover:bg-gray-50">
<td class="px-4 py-3">
<input type="checkbox" :value="'{{ $issue->id }}'" x-model="selected"
class="rounded border-gray-300 text-indigo-600 focus:ring-indigo-500">
</td>
<td class="px-4 py-3">
@php
$statusColors = [
'unresolved' => 'bg-red-100 text-red-800',
'resolved' => 'bg-green-100 text-green-800',
'ignored' => 'bg-yellow-100 text-yellow-800',
'muted' => 'bg-gray-100 text-gray-600',
];
$levelColors = [
'fatal' => 'bg-red-600',
'error' => 'bg-red-400',
'warning' => 'bg-yellow-400',
'info' => 'bg-blue-400',
'debug' => 'bg-gray-400',
];
@endphp
<span class="inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full text-xs font-medium {{ $statusColors[$issue->status] ?? 'bg-gray-100 text-gray-600' }}">
<span class="w-1.5 h-1.5 rounded-full {{ $levelColors[$issue->level] ?? 'bg-gray-400' }}"></span>
{{ ucfirst($issue->status) }}
</span>
</td>
<td class="px-4 py-3">
<a href="{{ route('projects.issues.show', [$project, $issue]) }}" class="block">
<div class="text-sm font-medium text-gray-900 truncate max-w-lg">{{ $issue->title }}</div>
@if($issue->culprit)
<div class="text-xs text-gray-500 truncate max-w-lg mt-0.5">{{ $issue->culprit }}</div>
@endif
</a>
</td>
<td class="px-4 py-3 text-right text-sm text-gray-700 font-mono">
{{ number_format($issue->times_seen) }}
</td>
<td class="px-4 py-3 text-right text-sm text-gray-500" title="{{ $issue->last_seen_at }}">
{{ $issue->last_seen_at->diffForHumans() }}
</td>
</tr>
@endforeach
</tbody>
</table>
<div class="px-4 py-3 border-t border-gray-200">
{{ $issues->links() }}
</div>
@endif
</div>
</div>
</div>
</x-app-layout>