Build hybrid ticketing inbox
This commit is contained in:
@@ -10,6 +10,7 @@ use Dashboard\Ticketing\Models\TicketingProject;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Inertia\Inertia;
|
||||
use Inertia\Response;
|
||||
|
||||
@@ -45,12 +46,35 @@ class TicketController extends Controller
|
||||
$agentGroupIds = $this->agentGroupIds();
|
||||
$isAgent = count($agentGroupIds) > 0;
|
||||
|
||||
$baseQuery = Ticket::query();
|
||||
|
||||
if ($isAgent) {
|
||||
$baseQuery->whereIn('group_id', $agentGroupIds);
|
||||
} else {
|
||||
$baseQuery->where('submitter_id', $user->id);
|
||||
}
|
||||
|
||||
$viewCounts = $isAgent
|
||||
? [
|
||||
'all' => (clone $baseQuery)->whereNotIn('status', ['resolved', 'closed'])->count(),
|
||||
'mine' => (clone $baseQuery)->where('assigned_to', $user->id)->whereNotIn('status', ['resolved', 'closed'])->count(),
|
||||
'unassigned' => (clone $baseQuery)->whereNull('assigned_to')->whereNotIn('status', ['resolved', 'closed'])->count(),
|
||||
'pending' => (clone $baseQuery)->where('status', 'pending')->count(),
|
||||
'resolved' => (clone $baseQuery)->whereIn('status', ['resolved', 'closed'])->count(),
|
||||
]
|
||||
: [
|
||||
'all' => (clone $baseQuery)->count(),
|
||||
'mine' => 0,
|
||||
'unassigned' => 0,
|
||||
'pending' => (clone $baseQuery)->where('status', 'pending')->count(),
|
||||
'resolved' => (clone $baseQuery)->whereIn('status', ['resolved', 'closed'])->count(),
|
||||
];
|
||||
|
||||
$query = Ticket::with(['group', 'priority', 'project']);
|
||||
|
||||
if ($isAgent) {
|
||||
$query->whereIn('group_id', $agentGroupIds);
|
||||
|
||||
// Filters
|
||||
if ($request->filled('group_id')) {
|
||||
$query->where('group_id', $request->group_id);
|
||||
}
|
||||
@@ -60,24 +84,36 @@ class TicketController extends Controller
|
||||
if ($request->filled('priority_id')) {
|
||||
$query->where('priority_id', $request->priority_id);
|
||||
}
|
||||
if ($request->filled('project_id')) {
|
||||
$query->where('project_id', $request->project_id);
|
||||
}
|
||||
if ($request->filter === 'mine') {
|
||||
$query->where('assigned_to', $user->id);
|
||||
$query->where('assigned_to', $user->id)->whereNotIn('status', ['resolved', 'closed']);
|
||||
} elseif ($request->filter === 'unassigned') {
|
||||
$query->whereNull('assigned_to');
|
||||
$query->whereNull('assigned_to')->whereNotIn('status', ['resolved', 'closed']);
|
||||
} elseif ($request->filter === 'pending') {
|
||||
$query->where('status', 'pending');
|
||||
} elseif ($request->filter === 'resolved') {
|
||||
$query->whereIn('status', ['resolved', 'closed']);
|
||||
} elseif (!$request->filled('status')) {
|
||||
$query->whereNotIn('status', ['resolved', 'closed']);
|
||||
}
|
||||
} else {
|
||||
$query->where('submitter_id', $user->id);
|
||||
if ($request->filled('project_id')) {
|
||||
$query->where('project_id', $request->project_id);
|
||||
}
|
||||
if ($request->filter === 'pending') {
|
||||
$query->where('status', 'pending');
|
||||
} elseif ($request->filter === 'resolved') {
|
||||
$query->whereIn('status', ['resolved', 'closed']);
|
||||
}
|
||||
}
|
||||
|
||||
$tickets = $query->latest()->paginate(30)->withQueryString();
|
||||
|
||||
// Enrich with submitter name
|
||||
$userIds = $tickets->pluck('submitter_id')->merge($tickets->pluck('assigned_to'))->filter()->unique();
|
||||
$users = \DB::table('users')->whereIn('id', $userIds)->get(['id', 'name', 'email'])->keyBy('id');
|
||||
$users = DB::table('users')->whereIn('id', $userIds)->get(['id', 'name', 'email'])->keyBy('id');
|
||||
|
||||
$tickets->getCollection()->transform(function ($ticket) use ($users) {
|
||||
$ticket->submitter = $users[$ticket->submitter_id] ?? null;
|
||||
@@ -85,22 +121,76 @@ class TicketController extends Controller
|
||||
return $ticket;
|
||||
});
|
||||
|
||||
$groups = TicketingGroup::when($isAgent, fn($q) => $q->whereIn('id', $agentGroupIds))->get();
|
||||
$groups = TicketingGroup::when($isAgent, fn ($q) => $q->whereIn('id', $agentGroupIds))->get();
|
||||
$priorities = PriorityLevel::whereNull('group_id')
|
||||
->orWhereIn('group_id', $agentGroupIds ?? [])
|
||||
->orWhereIn('group_id', $agentGroupIds ?: [0])
|
||||
->orderBy('sort_order')
|
||||
->get();
|
||||
$projects = TicketingProject::when($isAgent, fn($q) => $q->whereIn('group_id', $agentGroupIds))
|
||||
$projects = TicketingProject::when($isAgent, fn ($q) => $q->whereIn('group_id', $agentGroupIds))
|
||||
->where('status', 'active')
|
||||
->get();
|
||||
|
||||
$projectCounts = (clone $baseQuery)
|
||||
->select('project_id', DB::raw('count(*) as aggregate'))
|
||||
->whereNotNull('project_id')
|
||||
->groupBy('project_id')
|
||||
->pluck('aggregate', 'project_id');
|
||||
|
||||
$projects->transform(function ($project) use ($projectCounts) {
|
||||
$project->ticket_count = (int) ($projectCounts[$project->id] ?? 0);
|
||||
return $project;
|
||||
});
|
||||
|
||||
$ticketDetail = null;
|
||||
$detailAgents = [];
|
||||
if ($request->filled('detail')) {
|
||||
$detailQuery = Ticket::with([
|
||||
'group',
|
||||
'priority',
|
||||
'project',
|
||||
'messages.attachments',
|
||||
'attachments',
|
||||
])->whereKey($request->detail);
|
||||
|
||||
if ($isAgent) {
|
||||
$detailQuery->whereIn('group_id', $agentGroupIds);
|
||||
} else {
|
||||
$detailQuery->where('submitter_id', $user->id);
|
||||
}
|
||||
|
||||
$dt = $detailQuery->first();
|
||||
|
||||
if ($dt) {
|
||||
$detailUserIds = collect([$dt->submitter_id, $dt->assigned_to])
|
||||
->merge($dt->messages->pluck('user_id'))
|
||||
->filter()
|
||||
->unique();
|
||||
$detailUsers = DB::table('users')->whereIn('id', $detailUserIds)->get(['id', 'name', 'email'])->keyBy('id');
|
||||
|
||||
$dt->submitter = $detailUsers[$dt->submitter_id] ?? null;
|
||||
$dt->assignee = $dt->assigned_to ? ($detailUsers[$dt->assigned_to] ?? null) : null;
|
||||
$dt->messages->each(function ($msg) use ($detailUsers) {
|
||||
$msg->author = $msg->user_id ? ($detailUsers[$msg->user_id] ?? null) : null;
|
||||
});
|
||||
$ticketDetail = $dt;
|
||||
|
||||
if ($isAgent) {
|
||||
$agentIds = TicketingAgentAccess::where('group_id', $dt->group_id)->pluck('user_id');
|
||||
$detailAgents = DB::table('users')->whereIn('id', $agentIds)->get(['id', 'name', 'email']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Inertia::render('Ticketing/Index', [
|
||||
'tickets' => $tickets,
|
||||
'groups' => $groups,
|
||||
'priorities' => $priorities,
|
||||
'projects' => $projects,
|
||||
'isAgent' => $isAgent,
|
||||
'filters' => $request->only(['group_id', 'status', 'priority_id', 'filter']),
|
||||
'filters' => $request->only(['group_id', 'status', 'priority_id', 'project_id', 'filter', 'detail']),
|
||||
'ticketDetail' => $ticketDetail,
|
||||
'detailAgents' => $detailAgents,
|
||||
'viewCounts' => $viewCounts,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -154,19 +244,17 @@ class TicketController extends Controller
|
||||
|
||||
$ticket->load(['group', 'priority', 'project', 'messages', 'attachments']);
|
||||
|
||||
// Enrich messages with user data
|
||||
$userIds = $ticket->messages->pluck('user_id')->filter()->unique();
|
||||
$users = \DB::table('users')->whereIn('id', $userIds)->get(['id', 'name', 'email'])->keyBy('id');
|
||||
$users = DB::table('users')->whereIn('id', $userIds)->get(['id', 'name', 'email'])->keyBy('id');
|
||||
|
||||
$ticket->messages->each(function ($msg) use ($users) {
|
||||
$msg->author = $msg->user_id ? ($users[$msg->user_id] ?? null) : null;
|
||||
});
|
||||
|
||||
// Agents for assignment picker
|
||||
$agents = [];
|
||||
if ($isAgent) {
|
||||
$agentIds = TicketingAgentAccess::where('group_id', $ticket->group_id)->pluck('user_id');
|
||||
$agents = \DB::table('users')->whereIn('id', $agentIds)->get(['id', 'name', 'email']);
|
||||
$agents = DB::table('users')->whereIn('id', $agentIds)->get(['id', 'name', 'email']);
|
||||
}
|
||||
|
||||
$priorities = PriorityLevel::where(fn($q) => $q->whereNull('group_id')->orWhere('group_id', $ticket->group_id))
|
||||
@@ -191,7 +279,7 @@ class TicketController extends Controller
|
||||
$priorities = PriorityLevel::where(fn($q) => $q->whereNull('group_id')->orWhere('group_id', $ticket->group_id))
|
||||
->orderBy('sort_order')->get();
|
||||
$agentIds = TicketingAgentAccess::where('group_id', $ticket->group_id)->pluck('user_id');
|
||||
$agents = \DB::table('users')->whereIn('id', $agentIds)->get(['id', 'name', 'email']);
|
||||
$agents = DB::table('users')->whereIn('id', $agentIds)->get(['id', 'name', 'email']);
|
||||
$projects = TicketingProject::where('group_id', $ticket->group_id)->get();
|
||||
|
||||
return Inertia::render('Ticketing/Edit', [
|
||||
@@ -217,7 +305,6 @@ class TicketController extends Controller
|
||||
'project_id' => 'nullable|exists:ticketing_projects,id',
|
||||
];
|
||||
|
||||
// assigned_to only settable by agents
|
||||
if ($this->isAgent($ticket->group_id)) {
|
||||
$rules['assigned_to'] = 'nullable|exists:users,id';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user