feat: initial dashboard-ticketing scaffold

This commit is contained in:
Joel Wedemire
2026-04-08 14:17:26 -07:00
parent 1448eb7cf4
commit 81d0d54f50
13 changed files with 980 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
<?php
namespace Dashboard\Ticketing\Http\Controllers;
use Dashboard\Ticketing\Models\Ticket;
use Dashboard\Ticketing\Models\TicketComment;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
class TicketCommentController extends Controller
{
public function store(Request $request, Ticket $ticket)
{
$user = auth()->user();
$isAdmin = in_array($user->role ?? '', ['admin', 'super_admin']);
abort_if(! $isAdmin && $ticket->user_id !== $user->id, 403);
$request->validate([
'body' => 'required|string',
'is_internal' => 'boolean',
]);
// Non-admins cannot post internal notes
$isInternal = $isAdmin && $request->boolean('is_internal');
TicketComment::create([
'ticket_id' => $ticket->id,
'user_id' => $user->id,
'body' => $request->body,
'is_internal' => $isInternal,
]);
return redirect()->route('ticketing.show', $ticket)->with('success', 'Comment added.');
}
}

View File

@@ -0,0 +1,156 @@
<?php
namespace Dashboard\Ticketing\Http\Controllers;
use Dashboard\Ticketing\Models\Ticket;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Inertia\Inertia;
class TicketController extends Controller
{
public function index(Request $request)
{
$user = auth()->user();
$isAdmin = in_array($user->role ?? '', ['admin', 'super_admin']);
$query = Ticket::with(['submitter:id,name', 'assignee:id,name']);
if (! $isAdmin) {
$query->where('user_id', $user->id);
}
if ($search = $request->get('search')) {
$query->where(function ($q) use ($search) {
$q->where('title', 'like', "%{$search}%")
->orWhere('description', 'like', "%{$search}%");
});
}
if ($status = $request->get('status')) {
$query->where('status', $status);
}
if ($priority = $request->get('priority')) {
$query->where('priority', $priority);
}
if ($category = $request->get('category')) {
$query->where('category', $category);
}
$tickets = $query->latest()->paginate(25)->withQueryString();
return Inertia::render('Ticketing/Index', [
'tickets' => $tickets,
'search' => $request->get('search', ''),
'statusFilter' => $request->get('status', ''),
'priorityFilter' => $request->get('priority', ''),
'categoryFilter' => $request->get('category', ''),
'isAdmin' => $isAdmin,
]);
}
public function create()
{
return Inertia::render('Ticketing/Create');
}
public function store(Request $request)
{
$request->validate([
'title' => 'required|string|max:255',
'description' => 'required|string',
'category' => 'required|in:IT,Facilities,HR,Other',
'priority' => 'required|in:low,medium,high,urgent',
]);
Ticket::create([
'user_id' => auth()->id(),
'title' => $request->title,
'description' => $request->description,
'category' => $request->category,
'priority' => $request->priority,
'status' => 'open',
]);
return redirect()->route('ticketing.index')->with('success', 'Ticket submitted.');
}
public function show(Ticket $ticket)
{
$user = auth()->user();
$isAdmin = in_array($user->role ?? '', ['admin', 'super_admin']);
abort_if(! $isAdmin && $ticket->user_id !== $user->id, 403);
$ticket->load([
'submitter:id,name',
'assignee:id,name',
'comments.author:id,name',
]);
return Inertia::render('Ticketing/Show', [
'ticket' => $ticket,
'isAdmin' => $isAdmin,
]);
}
public function edit(Ticket $ticket)
{
$user = auth()->user();
$isAdmin = in_array($user->role ?? '', ['admin', 'super_admin']);
abort_if(! $isAdmin && $ticket->user_id !== $user->id, 403);
return Inertia::render('Ticketing/Edit', [
'ticket' => $ticket,
'isAdmin' => $isAdmin,
]);
}
public function update(Request $request, Ticket $ticket)
{
$user = auth()->user();
$isAdmin = in_array($user->role ?? '', ['admin', 'super_admin']);
abort_if(! $isAdmin && $ticket->user_id !== $user->id, 403);
$rules = [
'title' => 'required|string|max:255',
'description' => 'required|string',
'category' => 'required|in:IT,Facilities,HR,Other',
'priority' => 'required|in:low,medium,high,urgent',
];
if ($isAdmin) {
$rules['status'] = 'required|in:open,in_progress,resolved,closed';
$rules['assigned_to'] = 'nullable|exists:users,id';
}
$request->validate($rules);
$data = $request->only(['title', 'description', 'category', 'priority']);
if ($isAdmin) {
$data['status'] = $request->status;
$data['assigned_to'] = $request->assigned_to;
}
$ticket->update($data);
return redirect()->route('ticketing.show', $ticket)->with('success', 'Ticket updated.');
}
public function destroy(Ticket $ticket)
{
$user = auth()->user();
$isAdmin = in_array($user->role ?? '', ['admin', 'super_admin']);
abort_if(! $isAdmin && $ticket->user_id !== $user->id, 403);
$ticket->delete();
return redirect()->route('ticketing.index')->with('success', 'Ticket deleted.');
}
}