Sync SOP ke e-doc Plant & Add Subject dan penyempurnaan bagian matrix training karyawan
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
@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>
|
||||
.select2-container .select2-selection--single { height: 42px; border-radius: 0.75rem; border-color: #e2e8f0; background-color: #f8fafc; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered { line-height: 42px; font-size: 0.875rem; color: #334155; padding-left: 1rem; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow { height: 40px; right: 10px; }
|
||||
</style>
|
||||
|
||||
<div class="max-w-5xl mx-auto px-4 py-8" x-data="{ questionType: '{{ old('question_type', '') }}' }" @update-type.window="questionType = $event.detail">
|
||||
<div class="mb-6 flex items-center space-x-3">
|
||||
<a href="{{ route('admin.exams.questions') }}" class="text-slate-400 hover:text-blue-600 transition-colors">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path></svg>
|
||||
</a>
|
||||
<h2 class="text-2xl font-bold text-slate-800 tracking-tight">Tambah Soal Baru</h2>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-2xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<form action="{{ url('admin/exams/questions') }}" method="POST" class="p-6 sm:p-8 space-y-6">
|
||||
@csrf
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Subject / Materi Pembelajaran <span class="text-red-500">*</span></label>
|
||||
<select name="subject_id" class="select2 w-full text-sm" required>
|
||||
<option value="">-- Pilih Judul Materi --</option>
|
||||
@foreach($subjects as $subj)
|
||||
<option value="{{ $subj->id }}" {{ old('subject_id') == $subj->id ? 'selected' : '' }}>{{ $subj->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Departemen Khusus</label>
|
||||
<select name="department_id" class="select2 w-full text-sm">
|
||||
<option value="">-- Berlaku Semua Departemen --</option>
|
||||
@foreach($departments as $dept)
|
||||
<option value="{{ $dept->id }}" {{ old('department_id') == $dept->id ? 'selected' : '' }}>{{ $dept->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Posisi / Jabatan Khusus</label>
|
||||
<select name="position_id" class="select2 w-full text-sm">
|
||||
<option value="">-- Berlaku Semua Jabatan --</option>
|
||||
@foreach($positions as $pos)
|
||||
<option value="{{ $pos->id }}" {{ old('position_id') == $pos->id ? 'selected' : '' }}>{{ $pos->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Tipe Bentuk Soal <span class="text-red-500">*</span></label>
|
||||
<select name="question_type" class="select2 w-full text-sm" required id="question_type_select">
|
||||
<option value="">-- Pilih Tipe --</option>
|
||||
<option value="single" {{ old('question_type') == 'single' ? 'selected' : '' }}>Single Choice (1 Kunci Jawaban)</option>
|
||||
<option value="multiple" {{ old('question_type') == 'multiple' ? 'selected' : '' }}>Multiple Choice (Multi Jawaban)</option>
|
||||
<option value="true_false" {{ old('question_type') == 'true_false' ? 'selected' : '' }}>True / False (Benar / Salah)</option>
|
||||
<option value="descriptive" {{ old('question_type') == 'descriptive' ? 'selected' : '' }}>Descriptive (Esai / Uraian)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Tingkat Kesulitan Soal <span class="text-red-500">*</span></label>
|
||||
<select name="question_level" class="select2 w-full text-sm" required>
|
||||
<option value="mudah" {{ old('question_level') == 'mudah' ? 'selected' : '' }}>Mudah</option>
|
||||
<option value="sedang" {{ old('question_level') == 'sedang' ? 'selected' : '' }}>Sedang</option>
|
||||
<option value="sulit" {{ old('question_level') == 'sulit' ? 'selected' : '' }}>Sulit</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Passing Grade</label>
|
||||
<input type="number" name="passing_grade" value="{{ old('passing_grade', 0) }}" class="w-full px-3 py-2 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:border-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Durasi (Detik)</label>
|
||||
<input type="number" name="duration" value="{{ old('duration', 0) }}" class="w-full px-3 py-2 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:border-blue-500">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-slate-100 pt-6">
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Isi Teks Pertanyaan <span class="text-red-500">*</span></label>
|
||||
<textarea name="question_text" rows="4" required class="w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl focus:bg-white focus:ring-2 focus:ring-blue-500/20 text-sm" placeholder="Masukkan konten pertanyaan...">{{ old('question_text') }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-slate-100 pt-6" x-show="questionType !== ''" x-transition>
|
||||
<h3 class="text-sm font-bold text-slate-800 uppercase tracking-wider mb-4 border-l-4 border-blue-500 pl-3">Kerangka Pilihan & Kunci Jawaban</h3>
|
||||
|
||||
<div x-show="questionType === 'single'" class="space-y-3">
|
||||
@foreach(['A' => 'option_a', 'B' => 'option_b', 'C' => 'option_b', 'D' => 'option_d', 'E' => 'option_e'] as $key => $column)
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="radio" name="correct_answer" value="{{ $key }}" class="w-5 h-5 text-blue-600 border-slate-300">
|
||||
<input type="text" name="{{ $column }}" placeholder="Isi Pilihan {{ $key }}" class="flex-1 px-4 py-2 bg-white border border-slate-200 rounded-lg text-sm">
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div x-show="questionType === 'multiple'" class="space-y-3">
|
||||
@foreach(['A' => 'option_a', 'B' => 'option_b', 'C' => 'option_c', 'D' => 'option_d', 'E' => 'option_e'] as $key => $column)
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="checkbox" name="correct_answer[]" value="{{ $key }}" class="w-5 h-5 text-blue-600 border-slate-300 rounded">
|
||||
<input type="text" name="{{ $column }}" placeholder="Isi Pilihan {{ $key }}" class="flex-1 px-4 py-2 bg-white border border-slate-200 rounded-lg text-sm">
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div x-show="questionType === 'true_false'" class="flex gap-6">
|
||||
<label class="flex items-center gap-2 p-4 border border-slate-200 rounded-xl cursor-pointer hover:bg-slate-50 w-48">
|
||||
<input type="radio" name="correct_answer" value="True" class="w-5 h-5 text-emerald-600 border-slate-300">
|
||||
<span class="font-bold text-slate-700">True (Benar)</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2 p-4 border border-slate-200 rounded-xl cursor-pointer hover:bg-slate-50 w-48">
|
||||
<input type="radio" name="correct_answer" value="False" class="w-5 h-5 text-red-600 border-slate-300">
|
||||
<span class="font-bold text-slate-700">False (Salah)</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div x-show="questionType === 'descriptive'">
|
||||
<p class="text-xs text-slate-400 mb-2">Tuliskan panduan atau esensi jawaban yang dinilai benar:</p>
|
||||
<textarea name="option_a" rows="3" class="w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:border-blue-500" placeholder="Catatan/Kunci Esai untuk Korektor..."></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-6 flex justify-end space-x-3 border-t border-slate-100 mt-8">
|
||||
<a href="{{ route('admin.exams.questions') }}" class="px-5 py-2.5 text-sm font-semibold text-slate-600 hover:bg-slate-100 rounded-xl">Batal</a>
|
||||
<button type="submit" class="px-5 py-2.5 text-sm font-semibold text-white bg-blue-600 hover:bg-blue-700 rounded-xl shadow-md">Simpan Soal</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.select2').select2({ width: '100%' });
|
||||
$('#question_type_select').on('change', function() {
|
||||
window.dispatchEvent(new CustomEvent('update-type', { detail: $(this).val() }));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@@ -0,0 +1,146 @@
|
||||
@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>
|
||||
.select2-container .select2-selection--single { height: 42px; border-radius: 0.75rem; border-color: #e2e8f0; background-color: #f8fafc; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered { line-height: 42px; font-size: 0.875rem; color: #334155; padding-left: 1rem; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow { height: 40px; right: 10px; }
|
||||
</style>
|
||||
|
||||
<div class="max-w-5xl mx-auto px-4 py-8" x-data="{ questionType: '{{ old('question_type', $question->question_type) }}' }" @update-type.window="questionType = $event.detail">
|
||||
<div class="mb-6 flex items-center space-x-3">
|
||||
<a href="{{ route('admin.exams.questions') }}" class="text-slate-400 hover:text-blue-600 transition-colors">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path></svg>
|
||||
</a>
|
||||
<h2 class="text-2xl font-bold text-slate-800 tracking-tight">Edit Pertanyaan #{{ $question->id }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-2xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<form action="{{ url('admin/exams/questions/' . $question->id) }}" method="POST" class="p-6 sm:p-8 space-y-6">
|
||||
@csrf @method('PUT')
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Subject / Materi Pembelajaran <span class="text-red-500">*</span></label>
|
||||
<select name="subject_id" class="select2 w-full text-sm" required>
|
||||
@foreach($subjects as $subj)
|
||||
<option value="{{ $subj->id }}" {{ old('subject_id', $question->subject_id) == $subj->id ? 'selected' : '' }}>{{ $subj->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Departemen</label>
|
||||
<select name="department_id" class="select2 w-full text-sm">
|
||||
<option value="">-- Semua Departemen --</option>
|
||||
@foreach($departments as $dept)
|
||||
<option value="{{ $dept->id }}" {{ old('department_id', $question->department_id) == $dept->id ? 'selected' : '' }}>{{ $dept->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Posisi / Jabatan</label>
|
||||
<select name="position_id" class="select2 w-full text-sm">
|
||||
<option value="">-- Semua Jabatan --</option>
|
||||
@foreach($positions as $pos)
|
||||
<option value="{{ $pos->id }}" {{ old('position_id', $question->position_id) == $pos->id ? 'selected' : '' }}>{{ $pos->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Tipe Bentuk Soal <span class="text-red-500">*</span></label>
|
||||
<select name="question_type" class="select2 w-full text-sm" required id="question_type_select">
|
||||
<option value="single" {{ $question->question_type == 'single' ? 'selected' : '' }}>Single Choice</option>
|
||||
<option value="multiple" {{ $question->question_type == 'multiple' ? 'selected' : '' }}>Multiple Choice</option>
|
||||
<option value="true_false" {{ $question->question_type == 'true_false' ? 'selected' : '' }}>True / False</option>
|
||||
<option value="descriptive" {{ $question->question_type == 'descriptive' ? 'selected' : '' }}>Deskriptif</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Tingkat Kesulitan <span class="text-red-500">*</span></label>
|
||||
<select name="question_level" class="select2 w-full text-sm" required>
|
||||
<option value="mudah" {{ $question->question_level == 'mudah' ? 'selected' : '' }}>Mudah</option>
|
||||
<option value="sedang" {{ $question->question_level == 'sedang' ? 'selected' : '' }}>Sedang</option>
|
||||
<option value="sulit" {{ $question->question_level == 'sulit' ? 'selected' : '' }}>Sulit</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Passing Grade</label>
|
||||
<input type="number" name="passing_grade" value="{{ old('passing_grade', $question->passing_grade) }}" class="w-full px-3 py-2 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:border-blue-500">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Durasi (Detik)</label>
|
||||
<input type="number" name="duration" value="{{ old('duration', $question->duration) }}" class="w-full px-3 py-2 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:border-blue-500">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-slate-100 pt-6">
|
||||
<label class="block text-sm font-bold text-slate-700 mb-2">Isi Teks Pertanyaan <span class="text-red-500">*</span></label>
|
||||
<textarea name="question_text" rows="4" required class="w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-sm focus:border-blue-500">{{ old('question_text', $question->question_text) }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-slate-100 pt-6" x-show="questionType !== ''" x-transition>
|
||||
<h3 class="text-sm font-bold text-slate-800 uppercase tracking-wider mb-4 border-l-4 border-blue-500 pl-3">Pengaturan Pilihan & Kunci Jawaban</h3>
|
||||
|
||||
@php
|
||||
// Pastikan array terstruktur aman untuk dibaca blade
|
||||
$checkedAnswers = is_array($question->correct_answer) ? $question->correct_answer : [$question->correct_answer];
|
||||
@endphp
|
||||
|
||||
<div x-show="questionType === 'single'" class="space-y-3">
|
||||
@foreach(['A' => 'option_a', 'B' => 'option_b', 'C' => 'option_c', 'D' => 'option_d', 'E' => 'option_e'] as $key => $col)
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="radio" name="correct_answer" value="{{ $key }}" {{ in_array($key, $checkedAnswers) ? 'checked' : '' }} class="w-5 h-5 text-blue-600 border-slate-300">
|
||||
<input type="text" name="{{ $col }}" value="{{ $question->$col }}" class="flex-1 px-4 py-2 bg-white border border-slate-200 rounded-lg text-sm">
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div x-show="questionType === 'multiple'" class="space-y-3">
|
||||
@foreach(['A' => 'option_a', 'B' => 'option_b', 'C' => 'option_c', 'D' => 'option_d', 'E' => 'option_e'] as $key => $col)
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="checkbox" name="correct_answer[]" value="{{ $key }}" {{ in_array($key, $checkedAnswers) ? 'checked' : '' }} class="w-5 h-5 text-blue-600 border-slate-300 rounded">
|
||||
<input type="text" name="{{ $col }}" value="{{ $question->$col }}" class="flex-1 px-4 py-2 bg-white border border-slate-200 rounded-lg text-sm">
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div x-show="questionType === 'true_false'" class="flex gap-6">
|
||||
<label class="flex items-center gap-2 p-4 border border-slate-200 rounded-xl cursor-pointer hover:bg-slate-50 w-48">
|
||||
<input type="radio" name="correct_answer" value="True" {{ in_array('True', $checkedAnswers) || in_array('opt_a', $checkedAnswers) ? 'checked' : '' }} class="w-5 h-5 text-emerald-600 border-slate-300">
|
||||
<span class="font-bold text-slate-700">True (Benar)</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2 p-4 border border-slate-200 rounded-xl cursor-pointer hover:bg-slate-50 w-48">
|
||||
<input type="radio" name="correct_answer" value="False" {{ in_array('False', $checkedAnswers) || in_array('opt_b', $checkedAnswers) ? 'checked' : '' }} class="w-5 h-5 text-red-600 border-slate-300">
|
||||
<span class="font-bold text-slate-700">False (Salah)</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div x-show="questionType === 'descriptive'">
|
||||
<textarea name="option_a" rows="3" class="w-full px-4 py-3 bg-slate-50 border border-slate-200 rounded-xl text-sm" placeholder="Catatan esai korektor...">{{ $question->option_a }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pt-6 flex justify-end space-x-3 border-t border-slate-100 mt-8">
|
||||
<a href="{{ route('admin.exams.questions') }}" class="px-5 py-2.5 text-sm font-semibold text-slate-600 hover:bg-slate-100 rounded-xl">Batal</a>
|
||||
<button type="submit" class="px-5 py-2.5 text-sm font-semibold text-white bg-blue-600 hover:bg-blue-700 rounded-xl shadow-md">Simpan Perubahan</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.select2').select2({ width: '100%' });
|
||||
$('#question_type_select').on('change', function() {
|
||||
window.dispatchEvent(new CustomEvent('update-type', { detail: $(this).val() }));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@@ -0,0 +1,230 @@
|
||||
@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>
|
||||
.select2-container .select2-selection--single { height: 38px; border-radius: 0.5rem; border-color: #e2e8f0; background-color: #f8fafc; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered { line-height: 38px; font-size: 0.875rem; color: #334155; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow { height: 36px; }
|
||||
</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">
|
||||
<form action="{{ url('admin/exams/questions/bulk-delete') }}" method="POST" x-show="selectedQuestions.length > 0" x-transition @submit="return confirmBulkDelete()">
|
||||
@csrf @method('DELETE')
|
||||
<template x-for="id in selectedQuestions" :key="id">
|
||||
<input type="hidden" name="question_ids[]" :value="id">
|
||||
</template>
|
||||
<button type="submit" class="inline-flex items-center px-4 py-2 bg-red-50 text-red-600 border border-red-200 rounded-lg text-sm font-bold hover:bg-red-100 shadow-sm transition-all">
|
||||
<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>
|
||||
|
||||
<a href="{{ url('admin/exams/questions/import') }}" class="inline-flex items-center px-4 py-2 bg-slate-800 text-white rounded-lg text-sm font-semibold hover:bg-slate-900 shadow-sm transition-all">
|
||||
<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>
|
||||
|
||||
<a href="{{ url('admin/exams/questions/create') }}" class="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-semibold hover:bg-blue-700 shadow-sm transition-all">
|
||||
+ Tambah Soal
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm mb-6">
|
||||
<form action="{{ route('admin.exams.questions') }}" method="GET">
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-6 gap-4 mb-4">
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-slate-500 mb-1">Departemen</label>
|
||||
<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>
|
||||
<label class="block text-xs font-semibold text-slate-500 mb-1">Posisi / Jabatan</label>
|
||||
<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>
|
||||
<label class="block text-xs font-semibold text-slate-500 mb-1">Subject / Materi</label>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-slate-500 mb-1">Tipe Soal</label>
|
||||
<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>
|
||||
<option value="descriptive" {{ request('question_type') == 'descriptive' ? 'selected' : '' }}>Deskriptif</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-slate-500 mb-1">Level</label>
|
||||
<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>
|
||||
<label class="block text-xs font-bold text-slate-500 uppercase mb-1">Pembuat Soal</label>
|
||||
<select name="creator_id" class="w-full px-3 py-2 bg-white border border-slate-200 rounded-lg text-sm focus:ring-blue-500" onchange="this.form.submit()">
|
||||
<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>
|
||||
|
||||
<div class="flex flex-col md:flex-row gap-4 items-center justify-between border-t border-slate-100 pt-4">
|
||||
<div class="w-full md:w-1/3">
|
||||
<input type="text" name="search" value="{{ request('search') }}" placeholder="Cari teks pertanyaan..." class="w-full px-4 py-2 bg-slate-50 border border-slate-200 rounded-lg text-sm focus:ring-blue-500">
|
||||
</div>
|
||||
<div class="flex gap-2 w-full md:w-auto">
|
||||
@if(request()->hasAny(['search', 'department_id', 'position_id', 'subject_id', 'question_type', 'question_level', 'created_by']))
|
||||
<a href="{{ route('admin.exams.questions') }}" class="px-5 py-2 bg-slate-100 text-slate-600 rounded-lg text-sm font-semibold hover:bg-slate-200 transition-all text-center w-full md:w-auto">Reset</a>
|
||||
@endif
|
||||
<button type="submit" class="px-5 py-2 bg-blue-600 text-white rounded-lg text-sm font-semibold hover:bg-blue-700 transition-all text-center w-full md:w-auto">
|
||||
Terapkan Filter
|
||||
</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">
|
||||
<thead class="bg-slate-50 text-slate-600 text-xs uppercase tracking-wider border-b border-slate-200">
|
||||
<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>
|
||||
<th class="px-4 py-4 font-semibold w-12">Q.ID</th>
|
||||
<th class="px-4 py-4 font-semibold w-1/5">Subject / Materi</th>
|
||||
<th class="px-4 py-4 font-semibold w-1/5">Penempatan</th>
|
||||
<th class="px-4 py-4 font-semibold">Tipe & Level</th>
|
||||
<th class="px-4 py-4 font-semibold w-1/3">Pertanyaan</th>
|
||||
<th class="px-4 py-4 font-semibold">Pembuat</th>
|
||||
<th class="px-4 py-4 font-semibold text-right">Aksi</th>
|
||||
</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">
|
||||
<div class="font-bold text-slate-800 max-w-[200px] truncate" title="{{ $q->subject->name ?? 'Materi Umum' }}">
|
||||
{{ $q->subject->name ?? 'Materi Umum' }}
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<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>
|
||||
<div class="mt-1">
|
||||
@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>
|
||||
@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>
|
||||
<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>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-right space-x-2 whitespace-nowrap">
|
||||
<a href="{{ url('admin/exams/questions/'.$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="{{ url('admin/exams/questions/'.$q->id.'/edit') }}" 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="{{ url('admin/exams/questions/'.$q->id) }}" method="POST" class="inline-block" onsubmit="return confirm('Hapus soal ini secara permanen?');">
|
||||
@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>
|
||||
<td colspan="8" class="px-4 py-12 text-center text-slate-500 font-medium">
|
||||
Belum ada data soal yang sesuai kriteria filter.
|
||||
</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
|
||||
@@ -0,0 +1,93 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<div class="flex items-center space-x-3">
|
||||
<a href="{{ route('admin.exams.questions') }}" class="text-slate-400 hover:text-blue-600 transition-colors">
|
||||
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path></svg>
|
||||
</a>
|
||||
<h2 class="text-2xl font-bold text-slate-800 tracking-tight">Pratinjau Soal</h2>
|
||||
</div>
|
||||
<a href="{{ url('admin/exams/questions/'.$question->id.'/edit') }}" class="px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-bold hover:bg-blue-700 transition-colors shadow-sm">
|
||||
Edit Konten Soal
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-2xl shadow-sm border border-slate-200 p-6 mb-6">
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-6">
|
||||
<div>
|
||||
<span class="block text-xs font-semibold text-slate-400 uppercase tracking-wider">ID Sistem</span>
|
||||
<span class="block text-sm font-mono font-bold text-slate-900 mt-0.5">#{{ $question->id }} <span class="text-xs font-normal text-slate-400">(Old ID: {{ $question->old_id ?? '-' }})</span></span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="block text-xs font-semibold text-slate-400 uppercase tracking-wider">Subject / Materi</span>
|
||||
<span class="block text-sm font-bold text-slate-800 mt-0.5">{{ $question->subject->name ?? 'Materi Umum' }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="block text-xs font-semibold text-slate-400 uppercase tracking-wider">Bentuk Tipe</span>
|
||||
<span class="inline-block mt-1 px-2 py-0.5 bg-indigo-50 text-indigo-700 rounded text-[10px] font-bold uppercase border border-indigo-100">
|
||||
{{ str_replace('_', ' ', $question->question_type) }}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="block text-xs font-semibold text-slate-400 uppercase tracking-wider">Tingkat Kesulitan</span>
|
||||
<span class="block text-sm font-bold mt-0.5 {{ $question->question_level == 'mudah' ? 'text-emerald-500' : ($question->question_level == 'sedang' ? 'text-amber-500' : 'text-red-500') }}">
|
||||
{{ strtoupper($question->question_level) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-slate-100 mt-4 pt-4 grid grid-cols-1 md:grid-cols-3 gap-4 text-xs text-slate-500">
|
||||
<div><b>Departemen Target:</b> {{ $question->department->name ?? 'Semua Departemen (Global)' }}</div>
|
||||
<div><b>Jabatan Target:</b> {{ $question->position->name ?? 'Semua Struktur Jabatan' }}</div>
|
||||
<div><b>Kelayakan Kelulusan:</b> Min score <span class="font-bold text-slate-800">{{ $question->passing_grade }}</span> (Durasi: {{ $question->duration }} detik)</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-2xl shadow-sm border border-slate-200 p-6 sm:p-8">
|
||||
<h4 class="text-xs font-bold text-slate-400 uppercase tracking-wider mb-3 border-b border-slate-100 pb-2">Konten Soal</h4>
|
||||
<div class="text-slate-800 text-base font-medium mb-8 leading-relaxed">
|
||||
{!! nl2br(e($question->question_text)) !!}
|
||||
</div>
|
||||
|
||||
<h4 class="text-xs font-bold text-slate-400 uppercase tracking-wider mb-4 border-b border-slate-100 pb-2">Struktur Kunci & Pilihan</h4>
|
||||
|
||||
<div class="space-y-20">
|
||||
@if($question->question_type === 'descriptive')
|
||||
<div class="p-4 bg-slate-50 border border-slate-200 rounded-xl">
|
||||
<span class="text-xs font-bold text-slate-400 uppercase block mb-1">Panduan Jawaban Kunci Esai:</span>
|
||||
<p class="text-slate-700 text-sm">{!! nl2br(e($question->option_a)) !!}</p>
|
||||
</div>
|
||||
@elseif($question->question_type === 'true_false')
|
||||
@php $correct = is_array($question->correct_answer) ? $question->correct_answer[0] : $question->correct_answer; @endphp
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center p-3 rounded-xl border {{ in_array($correct, ['True','opt_a']) ? 'bg-emerald-50/70 border-emerald-200 text-emerald-900 font-bold' : 'border-slate-100 text-slate-600' }}">
|
||||
<span class="w-6 text-center text-xs font-bold mr-2">✔</span> True (Benar)
|
||||
</div>
|
||||
<div class="flex items-center p-3 rounded-xl border {{ in_array($correct, ['False','opt_b']) ? 'bg-emerald-50/70 border-emerald-200 text-emerald-900 font-bold' : 'border-slate-100 text-slate-600' }}">
|
||||
<span class="w-6 text-center text-xs font-bold mr-2">✔</span> False (Salah)
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<div class="space-y-2">
|
||||
@php $arrKeys = is_array($question->correct_answer) ? $question->correct_answer : [$question->correct_answer]; @endphp
|
||||
@foreach(['A' => 'option_a', 'B' => 'option_b', 'C' => 'option_c', 'D' => 'option_d', 'E' => 'option_e'] as $k => $col)
|
||||
@if(!empty($question->$col))
|
||||
<div class="flex items-center justify-between p-3 rounded-xl border {{ in_array($k, $arrKeys) ? 'bg-emerald-50/70 border-emerald-200 text-emerald-900 font-bold' : 'border-slate-100 text-slate-600' }}">
|
||||
<div class="flex items-center">
|
||||
<span class="w-6 h-6 rounded-md text-xs font-mono font-bold bg-slate-100 flex items-center justify-center mr-3 {{ in_array($k, $arrKeys) ? 'bg-emerald-500 text-white' : '' }}">{{ $k }}</span>
|
||||
<span>{{ $question->$col }}</span>
|
||||
</div>
|
||||
@if(in_array($k, $arrKeys))
|
||||
<span class="text-xs bg-emerald-600 text-white px-2 py-0.5 rounded font-bold uppercase tracking-wider">Kunci</span>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user