Add white-labeled marketing portal for dispensary partners:
- Business branding settings table and model for white-labeling
- Portal middleware (EnsureMarketingPortalAccess) with contact_type check
- Portal route group at /portal/{business}/*
- DashboardController with stats and CannaiQ recommendations
- PromoController for viewing recommended/existing promos
- CampaignController with create/send/schedule/cancel
- ListController for managing contact lists
- Policies for MarketingCampaign and MarketingPromo
- White-labeled portal layout with custom branding CSS
- Marketing Portal link in Filament admin for buyer businesses
- MarketingPortalUserSeeder for development testing
- PORTAL_ACCESS.md documentation
81 lines
2.6 KiB
PHP
81 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Portal;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Branding\BusinessBrandingSetting;
|
|
use App\Models\Business;
|
|
use App\Models\Marketing\MarketingCampaign;
|
|
use App\Models\Marketing\MarketingPromo;
|
|
use App\Services\Marketing\PromoRecommendationService;
|
|
use Illuminate\Http\Request;
|
|
|
|
class DashboardController extends Controller
|
|
{
|
|
public function __construct(
|
|
protected PromoRecommendationService $promoService
|
|
) {}
|
|
|
|
public function index(Request $request, Business $business)
|
|
{
|
|
$branding = BusinessBrandingSetting::forBusiness($business);
|
|
|
|
// Get recommended promos for this business
|
|
$recommendedPromos = collect();
|
|
try {
|
|
// Get store external IDs for this business if available
|
|
$storeExternalIds = $business->cannaiqStores()
|
|
->pluck('external_id')
|
|
->toArray();
|
|
|
|
if (! empty($storeExternalIds)) {
|
|
$recommendations = $this->promoService->getRecommendations(
|
|
$business,
|
|
$storeExternalIds[0] ?? null,
|
|
limit: 5
|
|
);
|
|
$recommendedPromos = collect($recommendations['recommendations'] ?? []);
|
|
}
|
|
} catch (\Exception $e) {
|
|
// CannaiQ not configured or error - that's fine, show empty
|
|
}
|
|
|
|
// Get recent campaigns for this business
|
|
$recentCampaigns = MarketingCampaign::where('business_id', $business->id)
|
|
->with('list')
|
|
->latest()
|
|
->limit(5)
|
|
->get();
|
|
|
|
// Get active promos
|
|
$activePromos = MarketingPromo::forBusiness($business->id)
|
|
->currentlyActive()
|
|
->with('brand')
|
|
->limit(5)
|
|
->get();
|
|
|
|
// Get campaign stats
|
|
$campaignStats = [
|
|
'total' => MarketingCampaign::where('business_id', $business->id)->count(),
|
|
'sent' => MarketingCampaign::where('business_id', $business->id)
|
|
->whereIn('status', ['sent', 'completed'])
|
|
->count(),
|
|
'draft' => MarketingCampaign::where('business_id', $business->id)
|
|
->where('status', 'draft')
|
|
->count(),
|
|
'scheduled' => MarketingCampaign::where('business_id', $business->id)
|
|
->where('status', 'scheduled')
|
|
->count(),
|
|
];
|
|
|
|
return view('portal.dashboard', compact(
|
|
'business',
|
|
'branding',
|
|
'recommendedPromos',
|
|
'recentCampaigns',
|
|
'activePromos',
|
|
'campaignStats'
|
|
));
|
|
}
|
|
}
|