Files
ChatbotAI/app/Http/Controllers/Admin/KnowledgeItemController.php
2026-05-18 08:56:23 +08:00

153 lines
5.1 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\StoreKnowledgeItemRequest;
use App\Jobs\ReindexKnowledgeItemJob;
use App\Models\Category;
use App\Models\KnowledgeItem;
use App\Services\KnowledgeBase\AuditService;
use App\Services\KnowledgeBase\IngestionService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
use RuntimeException;
class KnowledgeItemController extends Controller
{
public function __construct(
private readonly AuditService $auditService,
private readonly IngestionService $ingestionService,
) {}
public function index(Request $request): View
{
$query = KnowledgeItem::with('category')
->withTrashed();
if ($request->filled('category_id')) {
$query->where('category_id', $request->category_id);
}
if ($request->filled('item_type')) {
$query->where('item_type', $request->item_type);
}
if ($request->filled('search')) {
$query->where(function ($q) use ($request) {
$q->where('title', 'like', '%' . $request->search . '%')
->orWhere('content', 'like', '%' . $request->search . '%');
});
}
$items = $query->latest()->paginate(20)->withQueryString();
$categories = Category::active()->ordered()->get();
$typeLabels = KnowledgeItem::typeLabels();
return view('admin.knowledge-items.index', compact('items', 'categories', 'typeLabels'));
}
public function create(Request $request): View
{
$categories = Category::active()->ordered()->get();
$typeLabels = KnowledgeItem::typeLabels();
$prefillData = $request->only(['category_id', 'item_type', 'title', 'content']);
// prefillData berguna bila convert dari feedback
return view('admin.knowledge-items.create', compact('categories', 'typeLabels', 'prefillData'));
}
public function store(StoreKnowledgeItemRequest $request): RedirectResponse
{
$data = $request->validated();
$data['created_by'] = auth()->id();
$data['updated_by'] = auth()->id();
$item = KnowledgeItem::create($data);
$this->auditService->knowledgeItemCreated($item);
// Embed secara async
ReindexKnowledgeItemJob::dispatch($item->id);
return redirect()
->route('admin.knowledge-items.show', $item)
->with('success', "Knowledge item '{$item->title}' berjaya dicipta dan sedang di-embed.");
}
public function show(KnowledgeItem $knowledgeItem): View
{
$knowledgeItem->load('category', 'creator');
return view('admin.knowledge-items.show', compact('knowledgeItem'));
}
public function edit(KnowledgeItem $knowledgeItem): View
{
$categories = Category::active()->ordered()->get();
$typeLabels = KnowledgeItem::typeLabels();
return view('admin.knowledge-items.edit', compact('knowledgeItem', 'categories', 'typeLabels'));
}
public function update(StoreKnowledgeItemRequest $request, KnowledgeItem $knowledgeItem): RedirectResponse
{
$oldValues = $knowledgeItem->only(['title', 'content', 'is_active']);
$data = $request->validated();
$data['updated_by'] = auth()->id();
$knowledgeItem->update($data);
$this->auditService->knowledgeItemUpdated($knowledgeItem, $oldValues);
// Re-embed kerana kandungan mungkin berubah
ReindexKnowledgeItemJob::dispatch($knowledgeItem->id);
return redirect()
->route('admin.knowledge-items.show', $knowledgeItem)
->with('success', 'Knowledge item berjaya dikemaskini dan sedang di-embed semula.');
}
public function toggleStatus(KnowledgeItem $knowledgeItem): RedirectResponse
{
$newStatus = !$knowledgeItem->is_active;
$knowledgeItem->update(['is_active' => $newStatus]);
if (!$newStatus && $knowledgeItem->qdrant_point_id) {
$this->ingestionService->deactivateKnowledgeItemInQdrant($knowledgeItem);
$this->auditService->knowledgeItemDeactivated($knowledgeItem);
} elseif ($newStatus) {
// Reactivate — update payload Qdrant
ReindexKnowledgeItemJob::dispatch($knowledgeItem->id);
}
$status = $newStatus ? 'diaktifkan' : 'dinyahaktifkan';
return back()->with('success', "Item '{$knowledgeItem->title}' telah {$status}.");
}
public function reindex(KnowledgeItem $knowledgeItem): RedirectResponse
{
ReindexKnowledgeItemJob::dispatch($knowledgeItem->id);
return back()->with('success', 'Re-embed telah dimulakan.');
}
public function destroy(KnowledgeItem $knowledgeItem): RedirectResponse
{
// Deactivate dalam Qdrant dulu
if ($knowledgeItem->qdrant_point_id) {
$this->ingestionService->deactivateKnowledgeItemInQdrant($knowledgeItem);
}
$knowledgeItem->delete(); // SoftDelete
return redirect()
->route('admin.knowledge-items.index')
->with('success', 'Knowledge item telah dipadam.');
}
}