create: add controller and views for assesment on role student
This commit is contained in:
parent
2973b83aa8
commit
00924f3b36
|
|
@ -5,9 +5,13 @@
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Literacy\LiteracyAssessment;
|
use App\Models\Literacy\LiteracyAssessment;
|
||||||
use App\Models\Literacy\LiteracyQuestion;
|
use App\Models\Literacy\LiteracyQuestion;
|
||||||
|
use App\Models\Literacy\LiteracyMaterial;
|
||||||
|
use App\Models\Literacy\LiteracyOption;
|
||||||
use App\Models\Literacy\LiteracyAnswer;
|
use App\Models\Literacy\LiteracyAnswer;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class LiteracyAssessmentController extends Controller
|
class LiteracyAssessmentController extends Controller
|
||||||
{
|
{
|
||||||
|
|
@ -38,11 +42,31 @@ public function index()
|
||||||
public function start($id)
|
public function start($id)
|
||||||
{
|
{
|
||||||
$assessment = LiteracyAssessment::where('id', $id)
|
$assessment = LiteracyAssessment::where('id', $id)
|
||||||
->where('user_id', Auth::id()) // Pastikan hanya asesmen milik student tersebut
|
->where('user_id', Auth::id())
|
||||||
->firstOrFail();
|
->firstOrFail();
|
||||||
|
|
||||||
|
// Ubah status asesmen menjadi in_progress
|
||||||
$assessment->update(['status' => 'in_progress']);
|
$assessment->update(['status' => 'in_progress']);
|
||||||
|
|
||||||
|
// Ambil semua pertanyaan terkait asesmen ini
|
||||||
|
$questions = LiteracyQuestion::all(); // Sesuaikan jika ada filter
|
||||||
|
|
||||||
|
// Insert jawaban kosong jika belum ada
|
||||||
|
foreach ($questions as $question) {
|
||||||
|
LiteracyAnswer::updateOrInsert(
|
||||||
|
[
|
||||||
|
'assessment_id' => $assessment->id,
|
||||||
|
'question_id' => $question->id,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'option_id' => null,
|
||||||
|
'answer_text' => null,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return redirect()->route('literacy_assessments_show', $id);
|
return redirect()->route('literacy_assessments_show', $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,7 +80,13 @@ public function show($id)
|
||||||
->firstOrFail();
|
->firstOrFail();
|
||||||
|
|
||||||
// Ambil semua pertanyaan, urutkan pilihan ganda dulu baru essay
|
// Ambil semua pertanyaan, urutkan pilihan ganda dulu baru essay
|
||||||
$questions = LiteracyQuestion::orderByRaw("FIELD(type, 'multiple_choice', 'essay')")->get();
|
$questions = LiteracyQuestion::orderByRaw("FIELD(type, 'multiple_choice', 'essay')")
|
||||||
|
->with([
|
||||||
|
'answers' => function ($query) use ($id) {
|
||||||
|
$query->where('assessment_id', $id);
|
||||||
|
}
|
||||||
|
])
|
||||||
|
->get();
|
||||||
|
|
||||||
return view('literacy.student.assessments.assessment', compact('assessment', 'questions'));
|
return view('literacy.student.assessments.assessment', compact('assessment', 'questions'));
|
||||||
}
|
}
|
||||||
|
|
@ -76,40 +106,178 @@ public function continue($id)
|
||||||
/**
|
/**
|
||||||
* Menyimpan jawaban siswa ke database secara otomatis saat memilih atau mengisi jawaban.
|
* Menyimpan jawaban siswa ke database secara otomatis saat memilih atau mengisi jawaban.
|
||||||
*/
|
*/
|
||||||
public function storeAnswer(Request $request, $assessmentId)
|
public function storeAnswer(Request $request, $assessmentId): JsonResponse
|
||||||
{
|
{
|
||||||
|
Log::info('Request Data:', $request->all());
|
||||||
|
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'question_id' => 'required|exists:literacy_questions,id',
|
'question_id' => 'required|exists:literacy_questions,id',
|
||||||
'answer' => 'nullable|string',
|
'answer' => 'nullable|string',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Pastikan pengguna memiliki asesmen ini
|
||||||
$assessment = LiteracyAssessment::where('id', $assessmentId)
|
$assessment = LiteracyAssessment::where('id', $assessmentId)
|
||||||
->where('user_id', Auth::id())
|
->where('user_id', Auth::id())
|
||||||
->firstOrFail();
|
->first();
|
||||||
|
|
||||||
|
if (!$assessment) {
|
||||||
|
return response()->json(['error' => 'Asesmen tidak ditemukan'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$questionId = $request->question_id;
|
||||||
|
$answerValue = $request->answer;
|
||||||
|
|
||||||
|
$question = LiteracyQuestion::find($questionId);
|
||||||
|
if (!$question) {
|
||||||
|
return response()->json(['error' => 'Pertanyaan tidak ditemukan'], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$answerData = ['option_id' => null, 'answer_text' => $answerValue];
|
||||||
|
|
||||||
|
if ($question->type === 'multiple_choice') {
|
||||||
|
$option = LiteracyOption::where('id', $answerValue)
|
||||||
|
->where('question_id', $questionId)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if (!$option) {
|
||||||
|
return response()->json(['error' => 'Jawaban tidak valid'], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$answerData = ['option_id' => $option->id, 'answer_text' => null];
|
||||||
|
}
|
||||||
|
|
||||||
// Simpan atau update jawaban siswa
|
|
||||||
LiteracyAnswer::updateOrCreate(
|
LiteracyAnswer::updateOrCreate(
|
||||||
[
|
[
|
||||||
'assessment_id' => $assessment->id,
|
'assessment_id' => $assessment->id,
|
||||||
'user_id' => Auth::id(),
|
'question_id' => $questionId,
|
||||||
'question_id' => $request->question_id,
|
|
||||||
],
|
],
|
||||||
[
|
$answerData
|
||||||
'answer' => $request->answer,
|
|
||||||
]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Cek apakah semua pertanyaan telah dijawab
|
// Hitung jumlah pertanyaan dalam asesmen ini
|
||||||
$totalQuestions = LiteracyQuestion::count();
|
$totalQuestions = $assessment->questions()->count();
|
||||||
|
|
||||||
|
// Hitung jumlah pertanyaan yang sudah dijawab
|
||||||
$answeredQuestions = LiteracyAnswer::where('assessment_id', $assessment->id)
|
$answeredQuestions = LiteracyAnswer::where('assessment_id', $assessment->id)
|
||||||
->whereNotNull('answer')
|
->where(function ($query) {
|
||||||
|
$query->whereNotNull('option_id')
|
||||||
|
->orWhere('answer_text', '!=', '');
|
||||||
|
})
|
||||||
->count();
|
->count();
|
||||||
|
|
||||||
// Jika semua pertanyaan sudah dijawab, ubah status asesmen menjadi "completed"
|
Log::info('Answered Questions:', ['answered' => $answeredQuestions, 'total' => $totalQuestions]);
|
||||||
|
|
||||||
|
// Jika semua pertanyaan sudah dijawab, update status ke `completed`
|
||||||
if ($answeredQuestions >= $totalQuestions) {
|
if ($answeredQuestions >= $totalQuestions) {
|
||||||
$assessment->update(['status' => 'completed']);
|
$assessment->update(['status' => 'completed']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json(['success' => true]);
|
return response()->json(['success' => true]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function submitAssessment($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$user = Auth::user();
|
||||||
|
$assessment = LiteracyAssessment::where('id', $id)
|
||||||
|
->where('user_id', $user->id)
|
||||||
|
->firstOrFail();
|
||||||
|
|
||||||
|
if ($assessment->status !== 'in_progress') {
|
||||||
|
return response()->json(['error' => 'Asesmen tidak sedang berjalan.'], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$answers = LiteracyAnswer::where('assessment_id', $id)->get();
|
||||||
|
|
||||||
|
$correctWeight = 0; // Total bobot jawaban benar
|
||||||
|
$totalWeight = 0; // Total bobot semua soal
|
||||||
|
|
||||||
|
foreach ($answers as $answer) {
|
||||||
|
$question = LiteracyQuestion::find($answer->question_id);
|
||||||
|
if (!$question)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$weight = $question->weight ?? ($question->type === 'essay' ? 5 : 1);
|
||||||
|
$totalWeight += $weight; // Tambah bobot soal ke total
|
||||||
|
|
||||||
|
if ($question->type === 'multiple_choice') {
|
||||||
|
// Cek apakah jawaban pilihan ganda benar
|
||||||
|
if ($answer->option_id && LiteracyOption::where('id', $answer->option_id)->where('is_correct', true)->exists()) {
|
||||||
|
$correctWeight += $weight;
|
||||||
|
}
|
||||||
|
} elseif ($question->type === 'essay') {
|
||||||
|
// Ambil kunci jawaban esai
|
||||||
|
$correctAnswer = strtolower(trim($question->essay_answer));
|
||||||
|
$userAnswer = strtolower(trim($answer->answer_text));
|
||||||
|
|
||||||
|
// Jika jawaban sama persis, beri skor penuh
|
||||||
|
if ($userAnswer === $correctAnswer) {
|
||||||
|
$correctWeight += $weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hitung skor akhir berdasarkan bobot
|
||||||
|
$score = $totalWeight > 0 ? ($correctWeight / $totalWeight) * 100 : 0;
|
||||||
|
|
||||||
|
// Simpan skor dan ubah status asesmen ke 'completed'
|
||||||
|
$assessment->update([
|
||||||
|
'score' => round($score, 2),
|
||||||
|
'status' => 'completed',
|
||||||
|
'assessed_at' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Buat asesmen baru untuk percobaan berikutnya
|
||||||
|
LiteracyAssessment::create([
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'status' => 'pending',
|
||||||
|
'score' => null,
|
||||||
|
'feedback' => '',
|
||||||
|
'assessed_at' => null,
|
||||||
|
'created_at' => now(),
|
||||||
|
'updated_at' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json(['message' => 'Asesmen berhasil diselesaikan.', 'score' => round($score, 2)], 200);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json(['error' => 'Terjadi kesalahan: ' . $e->getMessage()], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function viewResult($id)
|
||||||
|
{
|
||||||
|
// Ambil asesmen berdasarkan ID, pastikan asesmen milik user dan statusnya sudah 'completed'
|
||||||
|
$assessment = LiteracyAssessment::where('id', $id)
|
||||||
|
->where('user_id', Auth::id())
|
||||||
|
->where('status', 'completed')
|
||||||
|
->firstOrFail();
|
||||||
|
|
||||||
|
// Ambil semua pertanyaan, beserta jawaban dan opsi untuk asesmen ini
|
||||||
|
$questions = LiteracyQuestion::with([
|
||||||
|
'answers' => function ($query) use ($id) {
|
||||||
|
$query->where('assessment_id', $id);
|
||||||
|
},
|
||||||
|
'options'
|
||||||
|
])->get();
|
||||||
|
|
||||||
|
return view('literacy.student.assessments.result', compact('assessment', 'questions'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function result($id)
|
||||||
|
{
|
||||||
|
$assessment = LiteracyAssessment::where('id', $id)
|
||||||
|
->where('user_id', Auth::id())
|
||||||
|
->where('status', 'completed')
|
||||||
|
->firstOrFail();
|
||||||
|
|
||||||
|
$questions = LiteracyQuestion::with([
|
||||||
|
'answers' => function ($query) use ($id) {
|
||||||
|
$query->where('assessment_id', $id);
|
||||||
|
},
|
||||||
|
'options'
|
||||||
|
])->get();
|
||||||
|
|
||||||
|
return view('literacy.student.assessments.result', compact('assessment', 'questions'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,7 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<link rel="icon" href="./images/logo.png" type="image/png">
|
<link rel="icon" href="./images/logo.png" type="image/png">
|
||||||
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -231,7 +232,7 @@
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<!-- SIDEBAR -->
|
<!-- SIDEBAR -->
|
||||||
<nav class="col-md-2 d-none d-md-block sidebar sidebar-right-shadow">
|
<nav class="col-md-2 d-none d-md-block sidebar sidebar-right-shadow" style="position: sticky; top: 20px;">
|
||||||
<div class="sidebar-sticky" style="margin-top: 20px;">
|
<div class="sidebar-sticky" style="margin-top: 20px;">
|
||||||
<ul class="nav flex-column">
|
<ul class="nav flex-column">
|
||||||
<li class="nav-item" style="margin-bottom: 40px;">
|
<li class="nav-item" style="margin-bottom: 40px;">
|
||||||
|
|
@ -247,7 +248,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<div class="row align-items-start">
|
<div class="row align-items-start">
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
|
|
@ -260,7 +261,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<div class="row align-items-start">
|
<div class="row align-items-start">
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
|
|
@ -273,7 +274,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<div class="row align-items-start">
|
<div class="row align-items-start">
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
|
|
@ -292,75 +293,137 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<!-- ------------------------------------------------------------------------------------------ -->
|
|
||||||
|
<!-- CONTENT DAN NAVIGASI SOAL -->
|
||||||
<!-- CONTENT -->
|
@php
|
||||||
<main class="col-md-9">
|
$multipleChoiceQuestions = $questions->filter(fn($q) => $q->options->isNotEmpty());
|
||||||
{{-- @foreach ($questions as $question)
|
$essayQuestions = $questions->filter(fn($q) => $q->options->isEmpty());
|
||||||
<div class="mb-3">
|
$multipleChoiceNumber = 0;
|
||||||
<p>{{ $question->question_text }}</p>
|
$essayNumber = 0;
|
||||||
|
@endphp
|
||||||
@if ($question->type == 'multiple_choice')
|
|
||||||
@foreach ($question->options as $option)
|
|
||||||
<label>
|
|
||||||
<input type="radio" name="question_{{ $question->id }}" class="answer-input"
|
|
||||||
data-question-id="{{ $question->id }}" value="{{ $option->id }}">
|
|
||||||
{{ $option->option_text }}
|
|
||||||
</label><br>
|
|
||||||
@endforeach
|
|
||||||
@else
|
|
||||||
<textarea class="answer-input form-control" data-question-id="{{ $question->id }}"></textarea>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
@endforeach --}}
|
|
||||||
|
|
||||||
|
<main class="col-md-8">
|
||||||
<div class="grid grid-cols-12 gap-6 p-6">
|
<div class="grid grid-cols-12 gap-6 p-6">
|
||||||
<!-- Konten Asesmen -->
|
<div class="col-span-12 lg:col-span-9 space-y-8">
|
||||||
<div class="col-span-12 lg:col-span-9 space-y-8"> <!-- Menggunakan col-span-12 untuk mobile, dan lg:col-span-9 untuk desktop -->
|
<!-- Bagian Pilihan Ganda -->
|
||||||
<h1 class="text-xl font-bold">Harap menjawab semua pertanyaan</h1>
|
@if ($multipleChoiceQuestions->isNotEmpty())
|
||||||
<p class="text-gray-600 text-sm">Semua jawaban akan dinilai</p>
|
<h4 class="text-base font-semibold mt-6">Bagian 1: Pilihan Ganda</h4>
|
||||||
|
<p class="text-gray-500 text-sm mb-3">Pilih salah satu jawaban yang paling tepat.</p>
|
||||||
<!-- Loop Soal -->
|
|
||||||
@foreach ($questions as $question)
|
@foreach ($multipleChoiceQuestions as $question)
|
||||||
<div class="bg-white shadow-md rounded-lg p-4 border mb-4">
|
@php
|
||||||
<h5 class="text-base font-medium mb-3">
|
$multipleChoiceNumber++;
|
||||||
<!-- Menampilkan nomor dan soal dengan menjaga pemformatan -->
|
$savedAnswer = optional($question->answers->where('assessment_id', $assessment->id)->first());
|
||||||
<span class="whitespace-pre-line">{{ $loop->iteration }}. {{ $question->question_text }}</span>
|
@endphp
|
||||||
</h5>
|
<div class="bg-white shadow-md rounded-lg p-4 border mb-4" id="question-mc-{{ $multipleChoiceNumber }}">
|
||||||
|
<h5 class="text-base font-medium mb-3">
|
||||||
<!-- Pilihan Jawaban -->
|
<span class="whitespace-pre-line">{{ $multipleChoiceNumber }}. {{ $question->question_text }}</span>
|
||||||
<div class="mt-3">
|
</h5>
|
||||||
@if ($question->options->isNotEmpty())
|
|
||||||
<div class="space-y-3 hover:bg-gray-500"> <!-- Menambahkan jarak antar opsi dan membuatnya vertikal -->
|
<div class="mt-3">
|
||||||
|
<div class="space-y-3">
|
||||||
@foreach ($question->options as $option)
|
@foreach ($question->options as $option)
|
||||||
<label class="block p-3 border rounded-sm cursor-pointer w-100">
|
<label class="block p-3 border rounded-sm cursor-pointer w-100">
|
||||||
<input type="radio" name="question_{{ $question->id }}" value="{{ $option->id }}" class="form-radio mt-1" onchange="saveAnswer('{{ $question->id }}', '{{ $option->id }}')">
|
<input type="radio" name="question_{{ $question->id }}"
|
||||||
<span class="text-gray-700 text-md">{{ $option->option_text }}</span>
|
value="{{ $option->id }}" class="form-radio"
|
||||||
|
onchange="saveAnswer('{{ $question->id }}', '{{ $option->id }}'); updateQuestionUI('mc', '{{ $question->id }}');"
|
||||||
|
{{ $savedAnswer && $savedAnswer->option_id == $option->id ? 'checked' : '' }}>
|
||||||
|
<span>{{ $option->option_text }}</span>
|
||||||
</label>
|
</label>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
@else
|
</div>
|
||||||
<!-- Jika tidak ada option, gunakan textarea -->
|
|
||||||
<textarea name="question_{{ $question->id }}" class="w-100 h-24 p-3 border rounded-lg focus:ring focus:ring-blue-200" placeholder="Masukkan jawaban Anda di sini..." onchange="saveAnswer('{{ $question->id }}', this.value)"></textarea>
|
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
@endforeach
|
||||||
@endforeach
|
@endif
|
||||||
</div>
|
|
||||||
|
<!-- Bagian Isian -->
|
||||||
<!-- Navigasi Halaman -->
|
@if ($essayQuestions->isNotEmpty())
|
||||||
<div class="col-span-12 lg:col-span-3 bg-white shadow-lg rounded-lg p-4"> <!-- Menambahkan col-span-12 untuk tampilan mobile dan lg:col-span-3 untuk desktop -->
|
<h4 class="text-base font-semibold mt-6">Bagian 2: Isian</h4>
|
||||||
<h2 class="text-base font-medium mb-3">Navigasi Halaman</h2>
|
<p class="text-gray-500 text-sm mb-3">Jawablah pertanyaan berikut dengan jawaban yang sesuai.</p>
|
||||||
<div class="grid grid-cols-5 gap-2">
|
|
||||||
@for ($i = 1; $i <= 17; $i++)
|
@foreach ($essayQuestions as $question)
|
||||||
<button class="w-10 h-10 text-sm rounded-lg {{ $i == 6 ? 'bg-red-500 text-white' : 'bg-gray-100' }}">
|
@php
|
||||||
{{ $i }}
|
$essayNumber++;
|
||||||
</button>
|
$savedAnswer = optional($question->answers->where('assessment_id', $assessment->id)->first());
|
||||||
@endfor
|
@endphp
|
||||||
|
<div class="bg-white shadow-md rounded-lg p-4 border mb-4" id="question-essay-{{ $essayNumber }}">
|
||||||
|
<h5 class="text-base font-medium mb-3">
|
||||||
|
<span class="whitespace-pre-line">{{ $essayNumber }}. {{ $question->question_text }}</span>
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<div class="mt-3">
|
||||||
|
<textarea name="question_{{ $question->id }}"
|
||||||
|
class="w-100 h-24 p-3 border rounded-lg focus:ring focus:ring-blue-200"
|
||||||
|
placeholder="Masukkan jawaban Anda di sini..."
|
||||||
|
oninput="saveAnswer('{{ $question->id }}', this.value); updateQuestionUI('essay', '{{ $question->id }}');">{{ $savedAnswer ? $savedAnswer->answer_text : '' }}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- NAVIGASI NOMOR SOAL -->
|
||||||
|
<aside class="col-md-2 d-flex flex-column align-items-end" style="position: sticky; top: 20px; height: fit-content;">
|
||||||
|
<div class="card p-3">
|
||||||
|
<h5 class="font-bold mb-3">Navigasi Soal</h5>
|
||||||
|
|
||||||
|
<!-- Navigasi Pilihan Ganda -->
|
||||||
|
<div class="mb-3">
|
||||||
|
<h6 class="font-bold text-secondary">Pilihan Ganda</h6>
|
||||||
|
<div class="d-flex flex-wrap gap-2">
|
||||||
|
@php $multipleChoiceNumber = 0; @endphp
|
||||||
|
@foreach ($questions as $question)
|
||||||
|
@if ($question->options->isNotEmpty())
|
||||||
|
@php
|
||||||
|
$multipleChoiceNumber++;
|
||||||
|
$savedAnswer = $question->answers->where('assessment_id', $assessment->id)->first();
|
||||||
|
$btnClass = $savedAnswer && $savedAnswer->option_id ? 'btn-primary border-white' : 'btn-outline-secondary';
|
||||||
|
@endphp
|
||||||
|
<button id="nav-mc-{{ $multipleChoiceNumber }}"
|
||||||
|
class="btn {{ $btnClass }}"
|
||||||
|
onclick="navigateToQuestion('mc', {{ $multipleChoiceNumber }})"
|
||||||
|
data-question-id="{{ $question->id }}">
|
||||||
|
{{ $multipleChoiceNumber }}
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</main>
|
<!-- Navigasi Isian -->
|
||||||
|
<div class="mb-3">
|
||||||
|
<h6 class="font-bold text-secondary">Isian</h6>
|
||||||
|
<div class="d-flex flex-wrap gap-2">
|
||||||
|
@php $essayNumber = 0; @endphp
|
||||||
|
@foreach ($questions as $question)
|
||||||
|
@if ($question->options->isEmpty())
|
||||||
|
@php
|
||||||
|
$essayNumber++;
|
||||||
|
$savedAnswer = $question->answers->where('assessment_id', $assessment->id)->first();
|
||||||
|
$btnClass = $savedAnswer && $savedAnswer->answer_text ? 'btn-primary border-white' : 'btn-outline-secondary';
|
||||||
|
@endphp
|
||||||
|
<button id="nav-essay-{{ $essayNumber }}"
|
||||||
|
class="btn {{ $btnClass }}"
|
||||||
|
onclick="navigateToQuestion('essay', {{ $essayNumber }})"
|
||||||
|
data-question-id="{{ $question->id }}">
|
||||||
|
{{ $essayNumber }}
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-center">
|
||||||
|
<button type="button" class="btn btn-primary w-100 py-2 fw-semibold" onclick="checkUnansweredQuestions()">
|
||||||
|
Selesai
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
@include('literacy.student.assessments.modals.confirmation')
|
||||||
|
@include('literacy.student.assessments.modals.unanswered_warning')
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -386,20 +449,93 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function saveAnswer(questionId, answer) {
|
function checkUnansweredQuestions() {
|
||||||
// Kirim AJAX request ke controller untuk menyimpan jawaban
|
let unansweredCount = 0;
|
||||||
axios.post('{{ route('literacy_assessment_store_answer', $assessment->id) }}', {
|
|
||||||
question_id: questionId,
|
// Cek soal pilihan ganda (radio button)
|
||||||
answer: answer,
|
@foreach ($multipleChoiceQuestions as $question)
|
||||||
})
|
if (!$("input[name='question_{{ $question->id }}']:checked").val()) {
|
||||||
.then(response => {
|
unansweredCount++;
|
||||||
if (response.data.success) {
|
|
||||||
console.log('Jawaban disimpan!');
|
|
||||||
}
|
}
|
||||||
})
|
@endforeach
|
||||||
.catch(error => {
|
|
||||||
console.error('Terjadi kesalahan:', error);
|
// Cek soal isian (textarea)
|
||||||
});
|
@foreach ($essayQuestions as $question)
|
||||||
|
if (!$("textarea[name='question_{{ $question->id }}']").val().trim()) {
|
||||||
|
unansweredCount++;
|
||||||
|
}
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
console.log("Soal yang belum dijawab:", unansweredCount); // Debugging
|
||||||
|
|
||||||
|
if (unansweredCount > 0) {
|
||||||
|
$("#unansweredCount").text(unansweredCount);
|
||||||
|
$("#unansweredWarningModal").modal("show"); // Tampilkan modal peringatan
|
||||||
|
} else {
|
||||||
|
$("#confirmSubmitModal").modal("show"); // Tampilkan modal konfirmasi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
async function saveAnswer(questionId, answer) {
|
||||||
|
const assessmentId = "{{ $assessment->id }}";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/literacy/student/assessments/${assessmentId}/save-answer`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute("content")
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
question_id: questionId,
|
||||||
|
answer: answer
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
console.log("Jawaban berhasil disimpan:", data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Gagal menyimpan jawaban:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function updateNavigationButton(questionId) {
|
||||||
|
// const navButton = document.querySelector(`button[data-question-id='${questionId}']`);
|
||||||
|
|
||||||
|
// if (navButton) {
|
||||||
|
// navButton.classList.remove("btn-outline-secondary");
|
||||||
|
// navButton.classList.add("btn-primary", "border-white");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function navigateToQuestion(type, number) {
|
||||||
|
const questionElement = document.getElementById(`question-${type}-${number}`);
|
||||||
|
if (questionElement) {
|
||||||
|
questionElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function updateQuestionUI(type, questionId) {
|
||||||
|
const navButton = document.querySelector(`button[data-question-id='${questionId}']`);
|
||||||
|
const questionCard = document.getElementById(`question-${type}-${questionId}`);
|
||||||
|
|
||||||
|
if (navButton) {
|
||||||
|
navButton.classList.remove("btn-outline-secondary");
|
||||||
|
navButton.classList.add("btn-primary", "border-white");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (questionCard) {
|
||||||
|
questionCard.classList.add("border-blue-500");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@
|
||||||
style="margin-top: 12px; margin-left: 15px; color: #676767;"></i>
|
style="margin-top: 12px; margin-left: 15px; color: #676767;"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<a class="nav-link active" href="{{ route('literacy_teacher_questions') }}"
|
<a class="nav-link active" href="{{ route('literacy_student_materials') }}"
|
||||||
style="color: #34364A;" id="manageQuestionsLink">Materials</a>
|
style="color: #34364A;" id="manageQuestionsLink">Materials</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -317,9 +317,15 @@
|
||||||
<span class="badge
|
<span class="badge
|
||||||
@if ($assessment->status == 'completed') bg-success
|
@if ($assessment->status == 'completed') bg-success
|
||||||
@elseif ($assessment->status == 'in_progress') bg-warning
|
@elseif ($assessment->status == 'in_progress') bg-warning
|
||||||
@else bg-secondary
|
@else bg-secondary
|
||||||
@endif">
|
@endif">
|
||||||
{{ ucfirst($assessment->status) }}
|
@if ($assessment->status == 'completed')
|
||||||
|
Selesai
|
||||||
|
@elseif ($assessment->status == 'in_progress')
|
||||||
|
Dalam Pengerjaan
|
||||||
|
@else
|
||||||
|
Belum Dikerjakan
|
||||||
|
@endif
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ $assessment->score ?? 'Belum Dinilai' }}</td>
|
<td>{{ $assessment->score ?? 'Belum Dinilai' }}</td>
|
||||||
|
|
@ -327,12 +333,12 @@
|
||||||
@if ($assessment->status == 'pending')
|
@if ($assessment->status == 'pending')
|
||||||
<form action="{{ route('literacy_assessments_start', $assessment->id) }}" method="POST" style="display:inline;">
|
<form action="{{ route('literacy_assessments_start', $assessment->id) }}" method="POST" style="display:inline;">
|
||||||
@csrf
|
@csrf
|
||||||
<button type="submit" class="btn btn-primary">Mulai Mengerjakan</button>
|
<button type="submit" class="btn btn-sm btn-primary text-white">Mulai</button>
|
||||||
</form>
|
</form>
|
||||||
@elseif ($assessment->status == 'in_progress')
|
@elseif ($assessment->status == 'in_progress')
|
||||||
<a href="{{ route('literacy_assessments_continue', $assessment->id) }}" class="btn btn-warning">Lanjutkan</a>
|
<a href="{{ route('literacy_assessments_continue', $assessment->id) }}" class="btn btn-sm btn-warning text-white">Lanjutkan</a>
|
||||||
@else
|
@else
|
||||||
<button class="btn btn-secondary" disabled>Selesai</button>
|
<a href="{{ route('literacy_assessment_result', $assessment->id) }}" class="btn btn-sm btn-success">Lihat Hasil</a>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
@ -341,7 +347,7 @@
|
||||||
<td colspan="4" class="text-center text-muted">Belum ada asesmen</td>
|
<td colspan="4" class="text-center text-muted">Belum ada asesmen</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user