2026-05-30 22:15:16 +07:00
@ extends ( 'layouts.app' )
@ section ( 'content' )
< link href = " https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css " rel = " stylesheet " />
< script src = " https://code.jquery.com/jquery-3.7.1.min.js " ></ script >
< script src = " https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js " ></ script >
< style >
2026-06-05 13:39:13 +07:00
. select2 - container . select2 - selection -- single { height : 42 px ; border - radius : 0.5 rem ; border - color : #e2e8f0; background-color: #f8fafc; }
. select2 - container -- default . select2 - selection -- single . select2 - selection__rendered { line - height : 42 px ; font - size : 0.875 rem ; color : #334155; }
. select2 - container -- default . select2 - selection -- single . select2 - selection__arrow { height : 40 px ; }
2026-05-30 22:15:16 +07:00
</ style >
< div class = " max-w-7xl mx-auto px-4 py-8 "
x - data = " {
selectedQuestions: [],
selectAll: false,
toggleAll() {
if (this.selectAll) {
this.selectedQuestions = Array.from(document.querySelectorAll('.question-checkbox')).map(cb => cb.value);
} else {
this.selectedQuestions = [];
}
},
confirmBulkDelete() {
if(this.selectedQuestions.length === 0) {
alert('Pilih minimal satu soal untuk dihapus!');
return false;
}
return confirm('Yakin ingin menghapus ' + this.selectedQuestions.length + ' soal terpilih secara permanen?');
}
} " >
< div class = " flex flex-col md:flex-row md:items-center justify-between mb-6 gap-4 " >
< div >
< h2 class = " text-2xl font-bold text-slate-800 tracking-tight " > Bank Soal ( Question Bank ) </ h2 >
< p class = " text-sm text-slate-500 mt-1 " > Kelola dan filter total < span class = " font-bold text-blue-600 " > {{ $totalQuestions }} </ span > soal ujian / kuis .</ p >
</ div >
< div class = " flex flex-wrap items-center gap-3 " >
2026-06-05 13:39:13 +07:00
< form action = " { { route('admin.exams.questions.bulkDelete') }} " method = " POST " x - show = " selectedQuestions.length > 0 " x - transition @ submit = " return confirmBulkDelete() " >
2026-05-30 22:15:16 +07:00
@ csrf @ method ( 'DELETE' )
< template x - for = " id in selectedQuestions " : key = " id " >
< input type = " hidden " name = " question_ids[] " : value = " id " >
</ template >
2026-06-05 13:39:13 +07:00
< button type = " submit " class = " inline-flex items-center px-4 py-2 bg-red-50 text-red-600 border border-red-200 rounded-xl text-sm font-bold hover:bg-red-100 shadow-sm transition-all " >
2026-05-30 22:15:16 +07:00
< svg class = " w-4 h-4 mr-2 " fill = " none " stroke = " currentColor " viewBox = " 0 0 24 24 " >< path stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16 " ></ path ></ svg >
Bulk Delete ( < span x - text = " selectedQuestions.length " ></ span > )
</ button >
</ form >
2026-06-05 13:39:13 +07:00
< a href = " { { route('admin.exams.questions.import') }} " class = " inline-flex items-center px-4 py-2 bg-slate-800 text-white rounded-xl text-sm font-semibold hover:bg-slate-900 shadow-sm transition-all " >
2026-05-30 22:15:16 +07:00
< svg class = " w-4 h-4 mr-2 " fill = " none " stroke = " currentColor " viewBox = " 0 0 24 24 " >< path stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12 " ></ path ></ svg >
Import Soal
</ a >
2026-06-05 13:39:13 +07:00
< a href = " { { route('admin.exams.questions.create') }} " class = " inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-xl text-sm font-semibold hover:bg-blue-700 shadow-sm transition-all " >
2026-05-30 22:15:16 +07:00
+ Tambah Soal
</ a >
</ div >
</ div >
2026-06-05 13:39:13 +07:00
< div class = " bg-white p-6 rounded-2xl border border-slate-200 shadow-sm mb-6 " >
< form action = " { { route('admin.question-bank.index') }} " method = " GET " >
< button type = " submit " class = " hidden " aria - hidden = " true " ></ button >
< div class = " grid grid-cols-1 md:grid-cols-3 lg:grid-cols-6 gap-5 mb-5 " >
2026-05-30 22:15:16 +07:00
< div >
2026-06-05 13:39:13 +07:00
< label class = " block text-[11px] font-bold text-slate-500 uppercase tracking-wide mb-1.5 " > Departemen </ label >
2026-05-30 22:15:16 +07:00
< select name = " department_id " class = " select2 w-full text-sm " >
< option value = " " > Semua </ option >
@ foreach ( $departments as $dept )
< option value = " { { $dept->id }} " {{ request ( 'department_id' ) == $dept -> id ? 'selected' : '' }} > {{ $dept -> name }} </ option >
@ endforeach
</ select >
</ div >
< div >
2026-06-05 13:39:13 +07:00
< label class = " block text-[11px] font-bold text-slate-500 uppercase tracking-wide mb-1.5 " > Posisi / Jabatan </ label >
2026-05-30 22:15:16 +07:00
< select name = " position_id " class = " select2 w-full text-sm " >
< option value = " " > Semua </ option >
@ foreach ( $positions as $pos )
< option value = " { { $pos->id }} " {{ request ( 'position_id' ) == $pos -> id ? 'selected' : '' }} > {{ $pos -> name }} </ option >
@ endforeach
</ select >
</ div >
< div >
2026-06-05 13:39:13 +07:00
< label class = " block text-[11px] font-bold text-slate-500 uppercase tracking-wide mb-1.5 " > Subject / Materi </ label >
2026-06-04 08:36:18 +07:00
< select name = " subject_id " class = " select2 w-full text-sm " >
< option value = " " > Semua Materi </ option >
@ foreach ( $subjects as $subj )
< option value = " { { $subj->id }} " {{ request ( 'subject_id' ) == $subj -> id ? 'selected' : '' }} > {{ $subj -> name }} </ option >
@ endforeach
</ select >
2026-05-30 22:15:16 +07:00
</ div >
< div >
2026-06-05 13:39:13 +07:00
< label class = " block text-[11px] font-bold text-slate-500 uppercase tracking-wide mb-1.5 " > Tipe Soal </ label >
2026-05-30 22:15:16 +07:00
< select name = " question_type " class = " select2 w-full text-sm " >
< option value = " " > Semua </ option >
< option value = " single " {{ request ( 'question_type' ) == 'single' ? 'selected' : '' }} > Single Choice </ option >
< option value = " multiple " {{ request ( 'question_type' ) == 'multiple' ? 'selected' : '' }} > Multiple Choice </ option >
< option value = " true_false " {{ request ( 'question_type' ) == 'true_false' ? 'selected' : '' }} > True / False </ option >
2026-06-05 13:39:13 +07:00
< option value = " essay " {{ request ( 'question_type' ) == 'essay' ? 'selected' : '' }} > Esai / Deskriptif </ option >
2026-05-30 22:15:16 +07:00
</ select >
</ div >
< div >
2026-06-05 13:39:13 +07:00
< label class = " block text-[11px] font-bold text-slate-500 uppercase tracking-wide mb-1.5 " > Level </ label >
2026-05-30 22:15:16 +07:00
< select name = " question_level " class = " select2 w-full text-sm " >
< option value = " " > Semua </ option >
< option value = " mudah " {{ request ( 'question_level' ) == 'mudah' ? 'selected' : '' }} > Mudah ( Easy ) </ option >
< option value = " sedang " {{ request ( 'question_level' ) == 'sedang' ? 'selected' : '' }} > Sedang ( Medium ) </ option >
< option value = " sulit " {{ request ( 'question_level' ) == 'sulit' ? 'selected' : '' }} > Sulit ( Hard ) </ option >
</ select >
</ div >
< div >
2026-06-05 13:39:13 +07:00
< label class = " block text-[11px] font-bold text-slate-500 uppercase tracking-wide mb-1.5 " > Pembuat Soal </ label >
< select name = " creator_id " class = " w-full px-3 py-2.5 bg-slate-50 border border-slate-200 rounded-lg text-sm focus:ring-blue-500 " >
< option value = " " >-- Semua Trainer --</ option >
@ foreach ( $creators as $creator )
< option value = " { { $creator->id }} " {{ request ( 'creator_id' ) == $creator -> id ? 'selected' : '' }} >
{{ $creator -> first_name }} {{ $creator -> last_name }}
</ option >
@ endforeach
</ select >
</ div >
2026-05-30 22:15:16 +07:00
</ div >
2026-06-05 13:39:13 +07:00
< div class = " flex flex-col md:flex-row gap-4 items-center justify-between border-t border-slate-100 pt-5 mt-2 " >
< div class = " w-full flex-1 md:pr-10 " >
< div class = " relative " >
< div class = " absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none " >
< svg class = " w-5 h-5 text-slate-400 " fill = " none " stroke = " currentColor " viewBox = " 0 0 24 24 " >< path stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z " ></ path ></ svg >
</ div >
< input type = " text " name = " search " value = " { { request('search') }} " placeholder = " Ketik kata kunci untuk mencari di semua kolom (Teks Soal, Dept, Materi, ID, dll)... " class = " w-full pl-10 pr-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-all shadow-sm " >
</ div >
2026-05-30 22:15:16 +07:00
</ div >
2026-06-05 13:39:13 +07:00
< div class = " flex gap-2 w-full md:w-auto shrink-0 " >
@ if ( request () -> hasAny ([ 'search' , 'department_id' , 'position_id' , 'subject_id' , 'question_type' , 'question_level' , 'creator_id' ]))
< a href = " { { route('admin.question-bank.index') }} " class = " px-4 py-2.5 bg-slate-100 text-slate-600 rounded-xl text-sm font-semibold hover:bg-slate-200 transition-all text-center " title = " Reset Semua Filter " > Reset </ a >
2026-05-30 22:15:16 +07:00
@ endif
2026-06-05 13:39:13 +07:00
< button type = " submit " name = " action " value = " export_excel " class = " px-4 py-2.5 bg-emerald-50 text-emerald-700 border border-emerald-200 rounded-xl text-sm font-bold hover:bg-emerald-100 transition-all text-center flex items-center " title = " Download Excel " >
< svg class = " w-4 h-4 mr-1.5 " fill = " none " stroke = " currentColor " viewBox = " 0 0 24 24 " >< path stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z " ></ path ></ svg > Excel
</ button >
< button type = " submit " name = " action " value = " export_pdf " formtarget = " _blank " class = " px-4 py-2.5 bg-rose-50 text-rose-700 border border-rose-200 rounded-xl text-sm font-bold hover:bg-rose-100 transition-all text-center flex items-center " title = " Cetak PDF " >
< svg class = " w-4 h-4 mr-1.5 " fill = " none " stroke = " currentColor " viewBox = " 0 0 24 24 " >< path stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z " ></ path ></ svg > PDF
</ button >
< div class = " border-l border-slate-200 mx-1 " ></ div >
< button type = " submit " class = " px-6 py-2.5 bg-blue-600 text-white rounded-xl text-sm font-bold hover:bg-blue-700 shadow-md transition-all transform hover:-translate-y-0.5 text-center flex items-center " >
Cari / Filter
2026-05-30 22:15:16 +07:00
</ button >
</ div >
</ div >
</ form >
</ div >
< div class = " bg-white border border-slate-200 rounded-2xl overflow-hidden shadow-sm " >
< div class = " overflow-x-auto " >
< table class = " w-full text-left text-sm " >
2026-06-05 13:39:13 +07:00
< thead class = " bg-slate-50 text-slate-600 text-[11px] uppercase tracking-wider border-b border-slate-200 " >
2026-05-30 22:15:16 +07:00
< tr >
< th class = " px-4 py-4 w-10 text-center " >
< input type = " checkbox " x - model = " selectAll " @ change = " toggleAll " class = " w-4 h-4 text-blue-600 border-slate-300 rounded focus:ring-blue-500 cursor-pointer " >
</ th >
2026-06-05 13:39:13 +07:00
< th class = " px-4 py-4 font-bold w-12 " > Q . ID </ th >
< th class = " px-4 py-4 font-bold w-1/5 " > Subject / Materi </ th >
< th class = " px-4 py-4 font-bold w-1/5 " > Penempatan </ th >
< th class = " px-4 py-4 font-bold " > Tipe & Level </ th >
< th class = " px-4 py-4 font-bold w-1/3 " > Pertanyaan </ th >
< th class = " px-4 py-4 font-bold " > Pembuat </ th >
< th class = " px-4 py-4 font-bold text-right " > Aksi </ th >
2026-05-30 22:15:16 +07:00
</ tr >
</ thead >
< tbody class = " divide-y divide-slate-100 text-slate-700 " >
@ forelse ( $questions as $q )
< tr class = " hover:bg-slate-50 transition-colors " : class = " selectedQuestions.includes(' { { $q->id }}') ? 'bg-blue-50/50' : '' " >
< td class = " px-4 py-3 text-center " >
< input type = " checkbox " value = " { { $q->id }} " x - model = " selectedQuestions " class = " question-checkbox w-4 h-4 text-blue-600 border-slate-300 rounded focus:ring-blue-500 cursor-pointer " >
</ td >
< td class = " px-4 py-3 font-mono font-bold text-slate-500 " > {{ $q -> id }} </ td >
< td class = " px-4 py-3 " >
2026-06-04 08:36:18 +07:00
< div class = " font-bold text-slate-800 max-w-[200px] truncate " title = " { { $q->subject ->name ?? 'Materi Umum' }} " >
{{ $q -> subject -> name ? ? 'Materi Umum' }}
</ div >
2026-05-30 22:15:16 +07:00
</ td >
< td class = " px-4 py-3 " >
2026-06-04 08:36:18 +07:00
< span class = " font-semibold text-slate-700 block " > {{ $q -> department -> name ? ? 'Semua Dept' }} </ span >
< span class = " text-[11px] text-slate-400 block mt-0.5 " > {{ $q -> position -> name ? ? 'Semua Jabatan' }} </ span >
</ td >
< td class = " px-4 py-3 whitespace-nowrap " >
< span class = " px-2 py-0.5 bg-indigo-50 text-indigo-700 rounded text-[10px] font-bold uppercase tracking-wider border border-indigo-100 " >
{{ str_replace ( '_' , ' ' , $q -> question_type ) }}
</ span >
2026-05-30 22:15:16 +07:00
< div class = " mt-1 " >
2026-06-04 08:36:18 +07:00
@ if ( $q -> question_level == 'mudah' ) < span class = " text-[11px] font-bold text-emerald-500 " > Mudah </ span >
@ elseif ( $q -> question_level == 'sedang' ) < span class = " text-[11px] font-bold text-amber-500 " > Sedang </ span >
2026-05-30 22:15:16 +07:00
@ else < span class = " text-[11px] font-bold text-red-500 " > Sulit </ span > @ endif
</ div >
</ td >
< td class = " px-4 py-3 " >
< p class = " text-sm text-slate-800 line-clamp-2 " > {{ strip_tags ( $q -> question_text ) }} </ p >
</ td >
2026-06-04 08:36:18 +07:00
< td class = " px-4 py-3 whitespace-nowrap " >
< div class = " text-sm font-semibold text-slate-800 " > {{ $q -> creator -> first_name ? ? 'ID: ' . $q -> created_by }} </ div >
< div class = " text-[11px] text-slate-400 " >
@ if ( $q -> creator && $q -> creator -> hasRole ( 'trainer' )) Trainer @ else Staf / Admin @ endif
</ div >
2026-05-30 22:15:16 +07:00
</ td >
< td class = " px-4 py-3 text-right space-x-2 whitespace-nowrap " >
2026-06-05 13:39:13 +07:00
< a href = " { { route('admin.exams.questions.show', $q->id ) }} " class = " text-slate-400 hover:text-blue-600 " >< svg class = " w-5 h-5 inline " fill = " none " stroke = " currentColor " viewBox = " 0 0 24 24 " >< path stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M15 12a3 3 0 11-6 0 3 3 0 016 0z " ></ path >< path stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z " ></ path ></ svg ></ a >
< a href = " { { route('admin.exams.questions.edit', $q->id ) }} " class = " text-slate-400 hover:text-amber-500 " >< svg class = " w-5 h-5 inline " fill = " none " stroke = " currentColor " viewBox = " 0 0 24 24 " >< path stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z " ></ path ></ svg ></ a >
< form action = " { { route('admin.exams.questions.destroy', $q->id ) }} " method = " POST " class = " inline-block " onsubmit = " return confirm('Hapus soal ini secara permanen?'); " >
2026-05-30 22:15:16 +07:00
@ csrf @ method ( 'DELETE' )
< button type = " submit " class = " text-slate-400 hover:text-red-500 " >< svg class = " w-5 h-5 inline " fill = " none " stroke = " currentColor " viewBox = " 0 0 24 24 " >< path stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16 " ></ path ></ svg ></ button >
</ form >
</ td >
</ tr >
@ empty
< tr >
2026-06-04 08:36:18 +07:00
< td colspan = " 8 " class = " px-4 py-12 text-center text-slate-500 font-medium " >
2026-06-05 13:39:13 +07:00
< div class = " flex flex-col items-center justify-center " >
< svg class = " w-12 h-12 text-slate-300 mb-3 " fill = " none " stroke = " currentColor " viewBox = " 0 0 24 24 " >< path stroke - linecap = " round " stroke - linejoin = " round " stroke - width = " 2 " d = " M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z " ></ path ></ svg >
Tidak ada data soal yang sesuai dengan kriteria pencarian / filter .
</ div >
2026-05-30 22:15:16 +07:00
</ td >
</ tr >
@ endforelse
</ tbody >
</ table >
</ div >
@ if ( $questions -> hasPages ())
< div class = " p-4 border-t border-slate-100 bg-slate-50/50 " >
{{ $questions -> links () }}
</ div >
@ endif
</ div >
</ div >
< script >
$ ( document ) . ready ( function () {
$ ( '.select2' ) . select2 ({ width : '100%' });
});
</ script >
@ endsection