feat: add quick-create functionality for client categories in the schedule form

This commit is contained in:
I-Fun
2026-04-04 22:40:20 +07:00
parent 15c8d3ae7c
commit 79f2f22e5d
8 changed files with 320 additions and 131 deletions

View File

@@ -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) {

View File

@@ -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([

View File

@@ -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);
}