Files
hub/app/Http/Controllers/Seller/MessagingController.php
kelly 5bbc740962 feat: Implement Phase 9 (Campaign UX) and Phase 10 (Conversations/Messaging)
- Add marketing_channel_id to broadcasts table
- Create Campaign views (index, create, edit, show) with modern UX
- Implement test send functionality with provider abstraction
- Create Conversations data model (conversations, participants, messages)
- Create Messaging inbox UI with conversation threads
- Link broadcast sends to conversation system
- Add Marketing nav section (premium feature, gated by has_marketing flag)
- Update BroadcastController with sendTest method
- Create MessagingController with conversation management
- Add SMS provider support (Twilio, Telnyx, Cannabrands)
- Create comprehensive platform naming and style guide

Phase 9 Complete: Full campaign management UX
Phase 10 Complete: Messaging foundation ready for two-way communication
2025-11-20 23:43:47 -07:00

121 lines
3.4 KiB
PHP

<?php
namespace App\Http\Controllers\Seller;
use App\Http\Controllers\Controller;
use App\Models\Conversation;
use App\Models\Message;
use Illuminate\Http\Request;
class MessagingController extends Controller
{
/**
* Display messaging inbox with conversation list
*/
public function index(Request $request)
{
$business = $request->user()->currentBusiness;
$query = Conversation::where('business_id', $business->id)
->with(['primaryContact', 'latestMessage']);
// Filter by status
if ($request->has('status') && $request->status) {
$query->where('status', $request->status);
}
// Filter by channel
if ($request->has('channel') && $request->channel) {
$query->where('channel_type', $request->channel);
}
// Search
if ($request->has('search') && $request->search) {
$query->where(function ($q) use ($request) {
$q->where('subject', 'LIKE', "%{$request->search}%")
->orWhereHas('primaryContact', function ($contactQuery) use ($request) {
$contactQuery->where('name', 'LIKE', "%{$request->search}%")
->orWhere('email', 'LIKE', "%{$request->search}%")
->orWhere('phone', 'LIKE', "%{$request->search}%");
});
});
}
$conversations = $query
->orderByDesc('last_message_at')
->paginate(20);
return view('seller.messaging.index', compact('business', 'conversations'));
}
/**
* Display a specific conversation thread
*/
public function show(Request $request, Conversation $conversation)
{
$business = $request->user()->currentBusiness;
// Ensure business owns this conversation
if ($conversation->business_id !== $business->id) {
abort(403);
}
$conversation->load(['primaryContact', 'participants']);
$messages = $conversation->messages()
->with('contact')
->orderBy('created_at', 'asc')
->get();
return view('seller.messaging.show', compact('business', 'conversation', 'messages'));
}
/**
* Close a conversation
*/
public function close(Request $request, Conversation $conversation)
{
$business = $request->user()->currentBusiness;
if ($conversation->business_id !== $business->id) {
abort(403);
}
$conversation->close();
return back()->with('success', 'Conversation closed');
}
/**
* Reopen a conversation
*/
public function reopen(Request $request, Conversation $conversation)
{
$business = $request->user()->currentBusiness;
if ($conversation->business_id !== $business->id) {
abort(403);
}
$conversation->reopen();
return back()->with('success', 'Conversation reopened');
}
/**
* Archive a conversation
*/
public function archive(Request $request, Conversation $conversation)
{
$business = $request->user()->currentBusiness;
if ($conversation->business_id !== $business->id) {
abort(403);
}
$conversation->update(['status' => 'archived']);
return back()->with('success', 'Conversation archived');
}
}