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

36
routes/auth.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
// ── Login ─────────────────────────────────────────────────────────────────────
Route::get('/login', function () {
return view('auth.login');
})->name('login')->middleware('guest');
Route::post('/login', function (Request $request) {
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials, $request->boolean('remember'))) {
$request->session()->regenerate();
return redirect()->intended(route('admin.dashboard'));
}
return back()->withErrors([
'email' => 'E-mel atau kata laluan tidak tepat.',
])->onlyInput('email');
})->middleware('guest');
// ── Logout ────────────────────────────────────────────────────────────────────
Route::post('/logout', function (Request $request) {
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect()->route('chatbot.index');
})->name('logout')->middleware('auth');

8
routes/console.php Normal file
View File

@@ -0,0 +1,8 @@
<?php
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');

90
routes/web.php Normal file
View File

@@ -0,0 +1,90 @@
<?php
use App\Http\Controllers\Admin\AuditLogController;
use App\Http\Controllers\Admin\CategoryController;
use App\Http\Controllers\Admin\ChatFeedbackController;
use App\Http\Controllers\Admin\ChunkReviewController;
use App\Http\Controllers\Admin\DashboardController;
use App\Http\Controllers\Admin\DocumentController;
use App\Http\Controllers\Admin\KnowledgeItemController;
use App\Http\Controllers\Chatbot\ChatController;
use App\Http\Controllers\Chatbot\FeedbackController;
use Illuminate\Support\Facades\Route;
// ── Authentication ────────────────────────────────────────────────────────────
require __DIR__ . '/auth.php';
// ── Chatbot (Public) ──────────────────────────────────────────────────────────
Route::prefix('chatbot')->name('chatbot.')->group(function () {
Route::get('/', [ChatController::class, 'index'])->name('index');
Route::post('/ask', [ChatController::class, 'ask'])
->name('ask')
->middleware('throttle:20,1');
Route::post('/feedback', [FeedbackController::class, 'store'])->name('feedback');
});
// ── Admin Panel ───────────────────────────────────────────────────────────────
Route::prefix('admin')->name('admin.')->middleware(['auth', 'role:admin,staff'])->group(function () {
// Dashboard
Route::get('/', [DashboardController::class, 'index'])->name('dashboard');
// Kategori — admin sahaja (tiada show page, terus ke edit)
Route::resource('categories', CategoryController::class)
->except(['show'])
->middleware('role:admin');
Route::patch('categories/{category}/toggle-status', [CategoryController::class, 'toggleStatus'])
->name('categories.toggle-status')->middleware('role:admin');
// Dokumen
Route::resource('documents', DocumentController::class)->except(['destroy']);
Route::post('documents/{document}/upload-version', [DocumentController::class, 'uploadVersion'])
->name('documents.upload-version');
Route::patch('documents/{document}/toggle-status', [DocumentController::class, 'toggleStatus'])
->name('documents.toggle-status');
Route::post('documents/{document}/reindex', [DocumentController::class, 'reindex'])
->name('documents.reindex')->middleware('role:admin');
// Route chunks kini diuruskan oleh ChunkReviewController (enhanced dengan status filter)
Route::get('documents/{document}/versions/{version}/chunks', [ChunkReviewController::class, 'index'])
->name('documents.chunks');
Route::get('documents/{document}/versions/{version}/download', [DocumentController::class, 'download'])
->name('documents.download');
// Knowledge Items
Route::resource('knowledge-items', KnowledgeItemController::class);
Route::patch('knowledge-items/{knowledgeItem}/toggle-status', [KnowledgeItemController::class, 'toggleStatus'])
->name('knowledge-items.toggle-status');
Route::post('knowledge-items/{knowledgeItem}/reindex', [KnowledgeItemController::class, 'reindex'])
->name('knowledge-items.reindex');
// Chat Feedback & Review
Route::prefix('chat-feedback')->name('chat-feedback.')->group(function () {
Route::get('/', [ChatFeedbackController::class, 'index'])->name('index');
Route::get('{chatLog}', [ChatFeedbackController::class, 'show'])->name('show');
Route::post('{chatLog}/convert-to-faq', [ChatFeedbackController::class, 'convertToFaq'])
->name('convert-to-faq');
Route::patch('{chatLog}/toggle-flag', [ChatFeedbackController::class, 'toggleFlag'])
->name('toggle-flag');
});
// Chunk Review & Editing — admin sahaja
// Resource: /admin/chunks/{chunk}
Route::prefix('chunks')->name('chunks.')->middleware('role:admin')->group(function () {
Route::get('{chunk}', [ChunkReviewController::class, 'show'])->name('show');
Route::patch('{chunk}', [ChunkReviewController::class, 'update'])->name('update');
Route::post('{chunk}/exclude', [ChunkReviewController::class, 'exclude'])->name('exclude');
Route::post('{chunk}/include', [ChunkReviewController::class, 'include'])->name('include');
Route::post('{chunk}/reindex', [ChunkReviewController::class, 'reindex'])->name('reindex');
Route::get('{chunk}/split', [ChunkReviewController::class, 'splitForm'])->name('split');
Route::post('{chunk}/split', [ChunkReviewController::class, 'doSplit'])->name('do-split');
});
// Audit Logs — admin sahaja
Route::prefix('audit-logs')->name('audit-logs.')->middleware('role:admin')->group(function () {
Route::get('/', [AuditLogController::class, 'index'])->name('index');
Route::get('{auditLog}', [AuditLogController::class, 'show'])->name('show');
});
});
// Redirect root ke chatbot
Route::get('/', fn() => redirect()->route('chatbot.index'));