whereNull('parent_id') ->orderBy('sort_order') ->get(); } public function index(): View { $contracts = BrandContract::with(['client', 'category']) ->orderByDesc('end_date') ->get(); $clients = Client::orderBy('name')->get(); $categoryTree = $this->categoryTree(); return view('contracts.index', compact('contracts', 'clients', 'categoryTree')); } public function store(Request $request): RedirectResponse { $validated = $request->validate([ 'title' => 'required|string|max:255', 'client_id' => 'nullable|exists:clients,id', 'category_id' => 'required|exists:client_categories,id', 'start_date' => 'required|date', 'end_date' => 'required|date|after_or_equal:start_date', 'notes' => 'nullable|string', ]); $validated['is_active'] = true; BrandContract::create($validated); return back()->with('success', 'πŸ“ Contract added!'); } public function update(Request $request, BrandContract $contract): RedirectResponse { $validated = $request->validate([ 'title' => 'required|string|max:255', 'client_id' => 'nullable|exists:clients,id', 'category_id' => 'required|exists:client_categories,id', 'start_date' => 'required|date', 'end_date' => 'required|date|after_or_equal:start_date', 'notes' => 'nullable|string', 'is_active' => 'boolean', ]); $validated['is_active'] = $request->boolean('is_active', $contract->is_active); $contract->update($validated); return back()->with('success', 'πŸ“ Contract updated!'); } public function destroy(BrandContract $contract): RedirectResponse { $contract->delete(); return back()->with('success', 'πŸ“ Contract removed.'); } public function toggle(BrandContract $contract): RedirectResponse { $contract->update(['is_active' => ! $contract->is_active]); return back()->with('success', $contract->is_active ? 'βœ… Contract activated.' : '⏸️ Contract paused.'); } /** * AJAX: check if a category has an active exclusive contract. * Returns null if clear, or contract details if blocked. */ public function check(Request $request): JsonResponse { $categoryId = $request->integer('category_id'); $clientId = $request->integer('client_id'); if (! $categoryId) { return response()->json(null); } // Collect the category and its parent chain (so blocking a parent also blocks children) $category = ClientCategory::find($categoryId); $checkIds = [$categoryId]; if ($category?->parent_id) { $checkIds[] = $category->parent_id; } $contract = BrandContract::with(['client', 'category']) ->active() ->whereIn('category_id', $checkIds) ->first(); if (! $contract) { return response()->json(null); } // Allow if it's the contracted brand itself if ($clientId && $contract->client_id && $contract->client_id === $clientId) { return response()->json(null); } return response()->json([ 'id' => $contract->id, 'title' => $contract->title, 'client_name' => $contract->client?->name ?? 'Unknown', 'category' => $contract->category?->name ?? 'Unknown', 'end_date' => $contract->end_date->format('d M Y'), 'days_left' => $contract->days_remaining, ]); } }