Compare commits

...

2 Commits

  1. 19
      app/Http/Controllers/Api/ExerciseController.php
  2. 24
      app/Http/Resources/BlankResource.php
  3. 24
      app/Http/Resources/ChoiceResource.php
  4. 27
      app/Http/Resources/ExerciseResource.php
  5. 23
      app/Http/Resources/QuestionGroupResource.php
  6. 25
      app/Http/Resources/QuestionResource.php
  7. 22
      app/Http/Resources/SkillResource.php
  8. 12
      app/Models/Exercise.php
  9. 4
      app/Models/QuestionBlank.php
  10. 19
      app/Services/ExerciseService.php
  11. 8
      app/Services/QuestionService.php
  12. 3
      routes/api.php

@ -75,4 +75,23 @@ class ExerciseController extends Controller
], 500); ], 500);
} }
} }
public function detail($id)
{
$exercise = $this->exerciseService->detail($id);
if (empty($exercise)) {
return response()->json([
'status' => true,
'data' => $exercise,
'message' => 'Không có dữ liệu.',
]);
}
return response()->json([
'status' => true,
'data' => $exercise,
'message' => 'Lấy danh sách đề thi thành công.',
]);
}
} }

@ -0,0 +1,24 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class BlankResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'position' => $this->position,
'correct_answer' => $this->correct_answer,
'other_answers' => $this->other_answers,
];
}
}

@ -0,0 +1,24 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ChoiceResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'content' => $this->content,
'is_correct' => $this->is_correct,
'position' => $this->position,
];
}
}

@ -0,0 +1,27 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class ExerciseResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->lesson_name,
'description' => $this->description,
'level' => $this->level_label,
'year' => $this->year,
'skills' => SkillResource::collection($this->whenLoaded('skills')),
'question_groups' => QuestionGroupResource::collection($this->whenLoaded('questionGroups')),
];
}
}

@ -0,0 +1,23 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class QuestionGroupResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'content' => $this->content,
'questions' => QuestionResource::collection($this->whenLoaded('questions')),
];
}
}

@ -0,0 +1,25 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class QuestionResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'content' => $this->content,
'score' => $this->score,
'explanation' => $this->explanation,
'hint' => $this->hint,
'type' => [
'code' => $this->type->code ?? null,
'name' => $this->type->name ?? null,
],
'choices' => $this->when($this->type->code === 'multiple_choice', ChoiceResource::collection($this->choices)),
'blanks' => $this->when($this->type->code !== 'multiple_choice', BlankResource::collection($this->blanks)),
];
}
}

@ -0,0 +1,22 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class SkillResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name
];
}
}

@ -23,6 +23,18 @@ class Exercise extends Model
'media_object_id', 'media_object_id',
]; ];
protected $appends = ['level_label'];
public function getLevelLabelAttribute()
{
return match ($this->level) {
0 => 'easy',
1 => 'normal',
2 => 'hard',
default => 'normal',
};
}
public function subject() public function subject()
{ {
return $this->belongsTo(Subject::class, 'subject_id'); return $this->belongsTo(Subject::class, 'subject_id');

@ -17,6 +17,10 @@ class QuestionBlank extends Model
'other_answers', 'other_answers',
]; ];
protected $casts = [
'other_answers' => 'array', // Laravel tự động json_decode
];
public function question() public function question()
{ {
return $this->belongsTo(Question::class, 'question_id'); return $this->belongsTo(Question::class, 'question_id');

@ -2,6 +2,7 @@
namespace App\Services; namespace App\Services;
use App\Http\Resources\ExerciseResource;
use App\Models\Exercise; use App\Models\Exercise;
class ExerciseService class ExerciseService
@ -52,4 +53,22 @@ class ExerciseService
return $exercise->id; return $exercise->id;
} }
public function detail($id)
{
$exercise = Exercise::with([
'skills:id,name',
'questionGroups' => function ($q) {
$q->select('id', 'exercise_id', 'content');
},
'questionGroups.questions' => function ($q) {
$q->select('id', 'content', 'group_id', 'question_type_id', 'description', 'score', 'explanation', 'hint');
},
'questionGroups.questions.type:id,code,name',
'questionGroups.questions.choices',
'questionGroups.questions.blanks',
])->findOrFail($id);
return new ExerciseResource($exercise);
}
} }

@ -6,6 +6,7 @@ use App\Models\Question;
use App\Models\QuestionBlank; use App\Models\QuestionBlank;
use App\Models\QuestionChoice; use App\Models\QuestionChoice;
use App\Models\QuestionGroup; use App\Models\QuestionGroup;
use App\Models\QuestionType;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
class QuestionService class QuestionService
@ -59,19 +60,20 @@ class QuestionService
foreach ($data as $groupKey => $value) { foreach ($data as $groupKey => $value) {
$groupId = $groupIds[$groupKey]; $groupId = $groupIds[$groupKey];
foreach ($value->questions as $qIndex => $question) { foreach ($value->questions as $qIndex => $question) {
$questionType = QuestionType::where('code', $question->type)->first();
$questionTypeId = $questionType ? $questionType->id : 1;
$dataQuestion[] = [ $dataQuestion[] = [
'exercise_id' => $exerciseId, 'exercise_id' => $exerciseId,
'content' => $question->content, 'content' => $question->content,
'description' => $question->description ?? null, 'description' => $question->description ?? null,
'group_id' => $groupId, 'group_id' => $groupId,
'question_type_id' => 1, 'question_type_id' => $questionTypeId,
'level' => 2, 'level' => 2,
'score' => $question->score ?? null, 'score' => $question->score ?? null,
'explanation' => $question->explanation ?? null, 'explanation' => $question->explanation ?? null,
'hint' => $question->hint ?? null, 'hint' => $question->hint ?? null,
'created_at' => $now, 'created_at' => $now,
'updated_at' => $now, 'updated_at' => $now
'custom_key' => "{$groupKey}_{$qIndex}", // dùng để map lại
]; ];
$questionMap["{$groupKey}_{$qIndex}"] = [ $questionMap["{$groupKey}_{$qIndex}"] = [
'type' => $question->type, 'type' => $question->type,

@ -13,6 +13,7 @@ Route::middleware(['auth:api', 'role:admin'])->get('/user', function (Request $r
}); });
Route::middleware('auth:api')->group(function () { Route::middleware('auth:api')->group(function () {
Route::get('/exercise', [ExerciseController::class, 'index'])->name('exercise.index'); Route::get('/exercises', [ExerciseController::class, 'index'])->name('exercise.index');
Route::post('/exercise/create', [ExerciseController::class, 'create'])->name('exercise.create'); Route::post('/exercise/create', [ExerciseController::class, 'create'])->name('exercise.create');
Route::get('/exercise/{id}', [ExerciseController::class, 'detail'])->name('exercise.detail');
}); });

Loading…
Cancel
Save