diff --git a/app/Http/Controllers/BrandContractController.php b/app/Http/Controllers/BrandContractController.php index 542241f..9f6e6c4 100644 --- a/app/Http/Controllers/BrandContractController.php +++ b/app/Http/Controllers/BrandContractController.php @@ -88,21 +88,17 @@ class BrandContractController extends Controller { $categoryId = $request->integer('category_id'); $clientId = $request->integer('client_id'); + $dateStr = $request->input('date'); - if (! $categoryId) { + if (! $categoryId || empty($dateStr)) { 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; - } + $date = $dateStr ? \Carbon\Carbon::parse($dateStr) : today(); $contract = BrandContract::with(['client', 'category']) - ->active() - ->whereIn('category_id', $checkIds) + ->active($date) + ->where('category_id', $categoryId) ->first(); if (! $contract) { diff --git a/app/Http/Controllers/ClientCategoryController.php b/app/Http/Controllers/ClientCategoryController.php index 773fc5a..45ef9a4 100644 --- a/app/Http/Controllers/ClientCategoryController.php +++ b/app/Http/Controllers/ClientCategoryController.php @@ -46,6 +46,22 @@ class ClientCategoryController extends Controller return back()->with('success', '🏷️ Category added!'); } + public function quickStore(Request $request): \Illuminate\Http\JsonResponse + { + $validated = $request->validate([ + 'name' => 'required|string|max:100', + ]); + + $validated['slug'] = \Illuminate\Support\Str::slug($validated['name']); + if (ClientCategory::where('slug', $validated['slug'])->exists()) { + $validated['slug'] .= '-' . substr(uniqid(), -4); + } + + $category = ClientCategory::create($validated); + + return response()->json(['id' => $category->id, 'name' => $category->name, 'icon' => '🏷️']); + } + public function update(Request $request, ClientCategory $category): RedirectResponse { $validated = $request->validate([ diff --git a/app/Http/Controllers/EventController.php b/app/Http/Controllers/EventController.php index 26e2f0f..79a54a3 100644 --- a/app/Http/Controllers/EventController.php +++ b/app/Http/Controllers/EventController.php @@ -40,20 +40,33 @@ class EventController extends Controller $events = Event::with('client')->orderBy('start_time')->get(); $clients = Client::where('status', 'active')->orderBy('name')->get(); $categoryTree = $this->categoryTree(); + + $contracts = BrandContract::select('client_id', 'title')->get(); + $contents = ContentBrief::select('client_id', 'title')->get(); + + foreach ($events as $e) { + $e->has_contract = $e->client_id && $contracts->contains(fn($c) => $c->client_id === $e->client_id && stripos($c->title, $e->title) !== false); + $e->has_content = $e->client_id && $contents->contains(fn($c) => $c->client_id === $e->client_id && stripos($c->title, $e->title) !== false); + } // Format for FullCalendar $calendarEvents = $events->map(fn (Event $e) => [ 'id' => $e->id, 'title' => ($e->is_priority ? '⭐ ' : '') . $e->title, - 'start' => $e->start_time->toIso8601String(), - 'end' => $e->end_time?->toIso8601String(), + 'start' => $e->start_time->format('Y-m-d\TH:i:s'), + 'end' => $e->end_time?->format('Y-m-d\TH:i:s'), 'backgroundColor' => $e->color, 'borderColor' => $e->color, 'extendedProps' => [ - 'status' => $e->status->value, - 'client' => $e->client?->name, - 'type' => $e->event_type, - 'priority' => $e->is_priority, + 'status' => $e->status->value, + 'client' => $e->client?->name, + 'type' => $e->event_type, + 'priority' => $e->is_priority, + 'location' => $e->location, + 'description' => $e->description, + 'notes' => $e->notes, + 'has_contract' => $e->has_contract, + 'has_content' => $e->has_content, ], ]); @@ -192,21 +205,35 @@ class EventController extends Controller public function apiList(): JsonResponse { - $events = Event::with('client')->get()->map(fn (Event $e) => [ - 'id' => $e->id, - 'title' => ($e->is_priority ? '⭐ ' : '') . $e->title, - 'start' => $e->start_time->toIso8601String(), - 'end' => $e->end_time?->toIso8601String(), - 'backgroundColor' => $e->color, - 'borderColor' => $e->color, - 'allDay' => $e->is_all_day, - 'extendedProps' => [ - 'status' => $e->status->value, - 'client' => $e->client?->name, - 'type' => $e->event_type, - 'priority' => $e->is_priority, - ], - ]); + $eventsList = Event::with('client')->get(); + $contracts = BrandContract::select('client_id', 'title')->get(); + $contents = ContentBrief::select('client_id', 'title')->get(); + + $events = $eventsList->map(function (Event $e) use ($contracts, $contents) { + $hasContract = $e->client_id && $contracts->contains(fn($c) => $c->client_id === $e->client_id && stripos($c->title, $e->title) !== false); + $hasContent = $e->client_id && $contents->contains(fn($c) => $c->client_id === $e->client_id && stripos($c->title, $e->title) !== false); + + return [ + 'id' => $e->id, + 'title' => ($e->is_priority ? '⭐ ' : '') . $e->title, + 'start' => $e->start_time->format('Y-m-d\TH:i:s'), + 'end' => $e->end_time?->format('Y-m-d\TH:i:s'), + 'backgroundColor' => $e->color, + 'borderColor' => $e->color, + 'allDay' => $e->is_all_day, + 'extendedProps' => [ + 'status' => $e->status->value, + 'client' => $e->client?->name, + 'type' => $e->event_type, + 'priority' => $e->is_priority, + 'location' => $e->location, + 'description' => $e->description, + 'notes' => $e->notes, + 'has_contract' => $hasContract, + 'has_content' => $hasContent, + ], + ]; + }); return response()->json($events); } diff --git a/app/Models/BrandContract.php b/app/Models/BrandContract.php index 7f0ae5e..1fc9273 100644 --- a/app/Models/BrandContract.php +++ b/app/Models/BrandContract.php @@ -34,11 +34,12 @@ class BrandContract extends Model // ── Scopes ─────────────────────────────────────────────────── - public function scopeActive($query) + public function scopeActive($query, $date = null) { + $date = $date ?? today(); return $query->where('is_active', true) - ->where('start_date', '<=', today()) - ->where('end_date', '>=', today()); + ->where('start_date', '<=', $date) + ->where('end_date', '>=', $date); } // ── Helpers ────────────────────────────────────────────────── diff --git a/resources/views/content/create.blade.php b/resources/views/content/create.blade.php index ce2b3cf..95b121d 100644 --- a/resources/views/content/create.blade.php +++ b/resources/views/content/create.blade.php @@ -62,7 +62,7 @@
- +
@@ -116,7 +116,8 @@
+ :class="{ 'opacity-50 cursor-not-allowed': contractWarning }" + :disabled="contractWarning">🎬 Create Brief Cancel @@ -135,13 +136,32 @@ function contractCheck(checkUrl) { contractMessage: '', async checkContract() { if (!this.categoryId) { this.contractWarning = false; return; } - const params = new URLSearchParams({ category_id: this.categoryId, client_id: this.clientId || '' }); - const res = await fetch(checkUrl + '?' + params); - const data = await res.json(); - if (data) { - this.contractWarning = true; - this.contractMessage = `"${data.title}" β€” ${data.client_name} holds exclusive rights in the ${data.category} category until ${data.end_date} (${data.days_left} days left).`; - } else { + let dateVal = ''; + const targetDateEl = document.querySelector('input[name="target_date"]'); + if (targetDateEl && targetDateEl.value) { + dateVal = targetDateEl.value; + } + if (!dateVal) { + this.contractWarning = false; + return; + } + const params = new URLSearchParams({ + category_id: this.categoryId, + client_id: this.clientId || '', + date: dateVal + }); + try { + const res = await fetch(checkUrl + '?' + params); + if (!res.ok) throw new Error('Network error'); + const data = await res.json(); + if (data && data.title) { + this.contractWarning = true; + this.contractMessage = `"${data.title}" β€” ${data.client_name} holds exclusive rights in the ${data.category} category until ${data.end_date} (${data.days_left} days left).`; + } else { + this.contractWarning = false; + this.contractMessage = ''; + } + } catch (e) { this.contractWarning = false; this.contractMessage = ''; } diff --git a/resources/views/schedule/create.blade.php b/resources/views/schedule/create.blade.php index a2a3628..3227868 100644 --- a/resources/views/schedule/create.blade.php +++ b/resources/views/schedule/create.blade.php @@ -15,7 +15,7 @@
@csrf @@ -31,7 +31,100 @@ @error('title')

{{ $message }}

@enderror
-
+
{{-- Type --}}
@@ -45,44 +138,7 @@
{{-- Client --}} -
+
+
- {{-- Quick New Client mini-form --}} -
-

🐱 New Client Basic Info

-
-
- - -
-
- - -
-
- - -
-
- - -
+ {{-- Quick New Client mini-form --}} +