Files
ladill-qr-plus/app/Http/Controllers/Qr/CampaignController.php
T
isaacclad 95d73d1367
Deploy Ladill QR Plus / deploy (push) Successful in 1m6s
Add Campaigns module for grouping QR codes.
Let accounts organise codes by promo or launch, attach or detach codes, and view combined scan totals from the sidebar.
2026-07-16 20:43:02 +00:00

157 lines
4.8 KiB
PHP

<?php
namespace App\Http\Controllers\Qr;
use App\Http\Controllers\Controller;
use App\Models\Campaign;
use App\Models\QrCode;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\View\View;
class CampaignController extends Controller
{
public function index(Request $request): View
{
$account = ladill_account();
$campaigns = Campaign::query()
->where('user_id', $account->id)
->withCount('qrCodes')
->withSum('qrCodes', 'scans_total')
->latest()
->paginate(20)
->withQueryString();
$base = Campaign::query()->where('user_id', $account->id);
return view('qr.campaigns.index', [
'campaigns' => $campaigns,
'campaignCount' => (clone $base)->count(),
'activeCount' => (clone $base)->where('status', Campaign::STATUS_ACTIVE)->count(),
'codesInCampaigns' => QrCode::query()
->where('user_id', $account->id)
->whereNotNull('campaign_id')
->count(),
]);
}
public function create(): View
{
return view('qr.campaigns.create', [
'campaign' => new Campaign(['status' => Campaign::STATUS_ACTIVE]),
]);
}
public function store(Request $request): RedirectResponse
{
$account = ladill_account();
$data = $this->validated($request);
$campaign = Campaign::create([
...$data,
'user_id' => $account->id,
]);
return redirect()
->route('qr.campaigns.show', $campaign)
->with('success', 'Campaign created.');
}
public function show(Campaign $campaign): View
{
$this->authorizeCampaign($campaign);
$codes = $campaign->qrCodes()->latest()->get();
$availableCodes = QrCode::query()
->where('user_id', $campaign->user_id)
->where(function ($q) use ($campaign) {
$q->whereNull('campaign_id')->orWhere('campaign_id', $campaign->id);
})
->orderBy('label')
->get();
return view('qr.campaigns.show', [
'campaign' => $campaign,
'codes' => $codes,
'availableCodes' => $availableCodes,
'totalScans' => (int) $codes->sum('scans_total'),
]);
}
public function update(Request $request, Campaign $campaign): RedirectResponse
{
$this->authorizeCampaign($campaign);
$campaign->update($this->validated($request));
return back()->with('success', 'Campaign updated.');
}
public function destroy(Campaign $campaign): RedirectResponse
{
$this->authorizeCampaign($campaign);
QrCode::query()
->where('campaign_id', $campaign->id)
->update(['campaign_id' => null]);
$campaign->delete();
return redirect()
->route('qr.campaigns.index')
->with('success', 'Campaign deleted. QR codes were unassigned, not removed.');
}
public function attach(Request $request, Campaign $campaign): RedirectResponse
{
$this->authorizeCampaign($campaign);
$validated = $request->validate([
'qr_code_ids' => ['required', 'array', 'min:1'],
'qr_code_ids.*' => ['integer'],
]);
QrCode::query()
->where('user_id', $campaign->user_id)
->whereIn('id', $validated['qr_code_ids'])
->update(['campaign_id' => $campaign->id]);
return back()->with('success', 'QR codes added to campaign.');
}
public function detach(Campaign $campaign, QrCode $qrCode): RedirectResponse
{
$this->authorizeCampaign($campaign);
abort_unless((int) $qrCode->user_id === (int) $campaign->user_id, 403);
abort_unless((int) $qrCode->campaign_id === (int) $campaign->id, 404);
$qrCode->update(['campaign_id' => null]);
return back()->with('success', 'QR code removed from campaign.');
}
/** @return array<string, mixed> */
private function validated(Request $request): array
{
$data = $request->validate([
'name' => ['required', 'string', 'max:120'],
'description' => ['nullable', 'string', 'max:2000'],
'status' => ['required', Rule::in(array_keys(Campaign::STATUSES))],
'starts_at' => ['nullable', 'date'],
'ends_at' => ['nullable', 'date', 'after_or_equal:starts_at'],
]);
$data['description'] = $data['description'] ?? null;
$data['starts_at'] = $data['starts_at'] ?? null;
$data['ends_at'] = $data['ends_at'] ?? null;
return $data;
}
private function authorizeCampaign(Campaign $campaign): void
{
abort_unless((int) $campaign->user_id === (int) ladill_account()->id, 403);
}
}