First commit

This commit is contained in:
Saufi
2026-05-18 08:56:23 +08:00
commit fd3d3a4d2b
147 changed files with 22099 additions and 0 deletions

View File

@@ -0,0 +1,117 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Category;
use App\Models\ChatFeedback;
use App\Models\ChatLog;
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;
class ChatFeedbackController extends Controller
{
public function __construct(
private readonly AuditService $auditService,
private readonly IngestionService $ingestionService,
) {}
/**
* Senarai log chat dengan filter dan status feedback.
*/
public function index(Request $request): View
{
$query = ChatLog::with(['session', 'category', 'feedback'])
->latest();
if ($request->filled('has_answer')) {
$query->where('has_answer', (bool) $request->has_answer);
}
if ($request->filled('is_flagged')) {
$query->where('is_flagged', true);
}
if ($request->filled('category_id')) {
$query->where('category_id', $request->category_id);
}
if ($request->filled('rating')) {
$query->whereHas('feedback', fn($q) => $q->where('rating', $request->rating));
}
$logs = $query->paginate(20)->withQueryString();
$categories = Category::active()->ordered()->get();
return view('admin.chat-feedback.index', compact('logs', 'categories'));
}
/**
* Semak satu log chat dengan butiran penuh.
*/
public function show(ChatLog $chatLog): View
{
$chatLog->load(['session', 'category', 'feedback.convertedFaq']);
return view('admin.chat-feedback.show', compact('chatLog'));
}
/**
* Convert soalan yang tidak dijawab dengan baik kepada FAQ rasmi.
*/
public function convertToFaq(Request $request, ChatLog $chatLog): RedirectResponse
{
$validated = $request->validate([
'category_id' => ['required', 'exists:categories,id'],
'title' => ['required', 'string', 'max:500'],
'content' => ['required', 'string', 'max:10000'],
]);
$knowledgeItem = KnowledgeItem::create([
'category_id' => $validated['category_id'],
'item_type' => KnowledgeItem::TYPE_FAQ,
'title' => $validated['title'],
'content' => $validated['content'],
'is_active' => true,
'is_public' => true,
'created_by' => auth()->id(),
'updated_by' => auth()->id(),
]);
// Kemaskini feedback jika ada
if ($feedback = $chatLog->feedback) {
$feedback->update([
'converted_to_faq' => true,
'converted_faq_id' => $knowledgeItem->id,
'reviewed_by' => auth()->id(),
'reviewed_at' => now(),
]);
}
// Flag log chat sebagai dah diselesaikan
$chatLog->update(['is_flagged' => false]);
$this->auditService->faqConvertedFromFeedback($feedback, $knowledgeItem);
// Embed knowledge item baru
\App\Jobs\ReindexKnowledgeItemJob::dispatch($knowledgeItem->id);
return redirect()
->route('admin.knowledge-items.show', $knowledgeItem)
->with('success', "FAQ baru '{$knowledgeItem->title}' berjaya dicipta dari log chat.");
}
/**
* Toggle flag pada log chat untuk tanda perlu semakan.
*/
public function toggleFlag(ChatLog $chatLog): RedirectResponse
{
$chatLog->update(['is_flagged' => !$chatLog->is_flagged]);
return back()->with('success', $chatLog->is_flagged ? 'Log ditanda untuk semakan.' : 'Flag dibuang.');
}
}