- Redesign dashboard as daily briefing format with action-first layout - Consolidate sidebar menu structure (Dashboard as single link) - Fix CRM form styling to use consistent UI patterns - Add PWA icons and push notification groundwork - Update SuiteMenuResolver for cleaner navigation
204 lines
6.9 KiB
PHP
204 lines
6.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Seller\Crm;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Business;
|
|
use App\Models\Crm\CrmTask;
|
|
use App\Models\User;
|
|
use Illuminate\Http\Request;
|
|
|
|
class TaskController extends Controller
|
|
{
|
|
/**
|
|
* Display tasks listing
|
|
*/
|
|
public function index(Request $request, Business $business)
|
|
{
|
|
$user = $request->user();
|
|
|
|
$tasksQuery = CrmTask::where('seller_business_id', $business->id)
|
|
->with(['assignee', 'creator', 'contact', 'business'])
|
|
->orderBy('due_at');
|
|
|
|
// Filter by status (completed vs incomplete)
|
|
if ($request->filled('status')) {
|
|
if ($request->status === 'completed') {
|
|
$tasksQuery->whereNotNull('completed_at');
|
|
} elseif ($request->status === 'pending') {
|
|
$tasksQuery->whereNull('completed_at');
|
|
}
|
|
}
|
|
|
|
// Filter by assignee
|
|
if ($request->filled('assignee_id')) {
|
|
$tasksQuery->where('assigned_to', $request->assignee_id);
|
|
}
|
|
|
|
// Filter by type
|
|
if ($request->filled('type')) {
|
|
$tasksQuery->where('type', $request->type);
|
|
}
|
|
|
|
// Search filter
|
|
if ($request->filled('q')) {
|
|
$search = $request->q;
|
|
$tasksQuery->where(function ($q) use ($search) {
|
|
$q->where('title', 'ILIKE', "%{$search}%")
|
|
->orWhere('details', 'ILIKE', "%{$search}%");
|
|
});
|
|
}
|
|
|
|
$tasks = $tasksQuery->paginate(25);
|
|
|
|
// Return JSON for AJAX/API requests (live search)
|
|
if ($request->wantsJson()) {
|
|
return response()->json([
|
|
'data' => $tasks->map(fn ($t) => [
|
|
'id' => $t->id,
|
|
'name' => $t->title,
|
|
'type' => $t->type,
|
|
'assignee' => $t->assignee?->name ?? 'Unassigned',
|
|
'due_at' => $t->due_at?->format('M j, Y'),
|
|
])->values()->toArray(),
|
|
]);
|
|
}
|
|
|
|
// Get stats with single efficient query
|
|
$statsQuery = CrmTask::where('seller_business_id', $business->id)
|
|
->selectRaw('
|
|
SUM(CASE WHEN assigned_to = ? AND completed_at IS NULL THEN 1 ELSE 0 END) as my_tasks,
|
|
SUM(CASE WHEN completed_at IS NULL AND due_at < NOW() THEN 1 ELSE 0 END) as overdue,
|
|
SUM(CASE WHEN completed_at IS NULL AND DATE(due_at) = CURRENT_DATE THEN 1 ELSE 0 END) as due_today
|
|
', [$user->id])
|
|
->first();
|
|
|
|
$stats = [
|
|
'my_tasks' => $statsQuery->my_tasks ?? 0,
|
|
'overdue' => $statsQuery->overdue ?? 0,
|
|
'due_today' => $statsQuery->due_today ?? 0,
|
|
];
|
|
|
|
$counts = $stats; // View expects $counts
|
|
|
|
// Get team members for assignment filter
|
|
$teamMembers = User::whereHas('businesses', fn ($q) => $q->where('businesses.id', $business->id))->get();
|
|
|
|
// Get buyer businesses (accounts) for filtering
|
|
$buyerBusinesses = Business::where('type', 'buyer')
|
|
->orderBy('name')
|
|
->get(['id', 'name']);
|
|
|
|
return view('seller.crm.tasks.index', compact('business', 'tasks', 'counts', 'teamMembers', 'buyerBusinesses'));
|
|
}
|
|
|
|
/**
|
|
* Show create task form
|
|
*/
|
|
public function create(Request $request, Business $business)
|
|
{
|
|
$teamMembers = User::whereHas('businesses', fn ($q) => $q->where('businesses.id', $business->id))->get();
|
|
|
|
// Prefill from query params (when creating task from contact/account/etc)
|
|
$prefill = [
|
|
'title' => $request->get('title'),
|
|
'business_id' => $request->get('business_id'),
|
|
'contact_id' => $request->get('contact_id'),
|
|
'opportunity_id' => $request->get('opportunity_id'),
|
|
'conversation_id' => $request->get('conversation_id'),
|
|
'order_id' => $request->get('order_id'),
|
|
];
|
|
|
|
return view('seller.crm.tasks.create', compact('business', 'teamMembers', 'prefill'));
|
|
}
|
|
|
|
/**
|
|
* Store a new task
|
|
*/
|
|
public function store(Request $request, Business $business)
|
|
{
|
|
$validated = $request->validate([
|
|
'title' => 'required|string|max:255',
|
|
'details' => 'nullable|string',
|
|
'type' => 'required|in:call,email,meeting,follow_up,demo,other',
|
|
'priority' => 'required|in:low,normal,high,urgent',
|
|
'due_at' => 'required|date',
|
|
'assigned_to' => 'nullable|exists:users,id',
|
|
'contact_id' => 'nullable|exists:contacts,id',
|
|
'business_id' => 'nullable|exists:businesses,id',
|
|
]);
|
|
|
|
$task = CrmTask::create([
|
|
'title' => $validated['title'],
|
|
'details' => $validated['details'] ?? null,
|
|
'type' => $validated['type'],
|
|
'priority' => $validated['priority'],
|
|
'due_at' => $validated['due_at'],
|
|
'contact_id' => $validated['contact_id'] ?? null,
|
|
'business_id' => $validated['business_id'] ?? null,
|
|
'seller_business_id' => $business->id,
|
|
'created_by' => $request->user()->id,
|
|
'assigned_to' => $validated['assigned_to'] ?? $request->user()->id,
|
|
]);
|
|
|
|
return redirect()
|
|
->route('seller.business.crm.tasks.show', [$business->slug, $task])
|
|
->with('success', 'Task created successfully.');
|
|
}
|
|
|
|
/**
|
|
* Show task details
|
|
*/
|
|
public function show(Request $request, Business $business, CrmTask $task)
|
|
{
|
|
$task->load(['assignee', 'creator', 'contact', 'business', 'opportunity', 'order']);
|
|
|
|
return view('seller.crm.tasks.show', compact('business', 'task'));
|
|
}
|
|
|
|
/**
|
|
* Update task
|
|
*/
|
|
public function update(Request $request, Business $business, CrmTask $task)
|
|
{
|
|
$validated = $request->validate([
|
|
'title' => 'sometimes|string|max:255',
|
|
'details' => 'nullable|string',
|
|
'type' => 'sometimes|in:call,email,meeting,follow_up,demo,other',
|
|
'priority' => 'sometimes|in:low,normal,high,urgent',
|
|
'due_at' => 'sometimes|date',
|
|
'assigned_to' => 'nullable|exists:users,id',
|
|
]);
|
|
|
|
$task->update($validated);
|
|
|
|
return redirect()
|
|
->back()
|
|
->with('success', 'Task updated successfully.');
|
|
}
|
|
|
|
/**
|
|
* Delete task
|
|
*/
|
|
public function destroy(Request $request, Business $business, CrmTask $task)
|
|
{
|
|
$task->delete();
|
|
|
|
return redirect()
|
|
->route('seller.business.crm.tasks.index', $business->slug)
|
|
->with('success', 'Task deleted successfully.');
|
|
}
|
|
|
|
/**
|
|
* Mark task as complete
|
|
*/
|
|
public function complete(Request $request, Business $business, CrmTask $task)
|
|
{
|
|
$task->markComplete($request->user());
|
|
|
|
return redirect()
|
|
->back()
|
|
->with('success', 'Task marked as complete.');
|
|
}
|
|
}
|