Skip to content

Commit

Permalink
add timer to quiz
Browse files Browse the repository at this point in the history
  • Loading branch information
AmonDeShir committed Aug 16, 2024
1 parent f56ad7a commit a72a06d
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 4 deletions.
1 change: 1 addition & 0 deletions app/Http/Requests/QuizRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function rules(): array
return [
"name" => ["required", "string"],
"scheduled_at" => ["date", "date_format:Y-m-d H:i:s", "after:now"],
"duration" => ["integer", "min:1"],
];
}
}
1 change: 1 addition & 0 deletions app/Http/Resources/QuizResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public function toArray($request): array
"name" => $this->name,
"createdAt" => $this->created_at,
"updatedAt" => $this->updated_at,
"duration" => $this->duration,
"locked" => $this->isLocked,
"questions" => QuestionResource::collection($this->questions),
];
Expand Down
16 changes: 15 additions & 1 deletion app/Models/Quiz.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
* @property Carbon $created_at
* @property Carbon $updated_at
* @property Carbon $scheduled_at
* @property ?int $duration
* @property bool $isLocked
* @property ?Carbon $closeAt
* @property Collection<Question> $questions
* @property Collection<Answer> $answers
*/
Expand All @@ -29,6 +31,7 @@ class Quiz extends Model
protected $fillable = [
"name",
"scheduled_at",
"duration"
];

public function questions(): HasMany
Expand All @@ -43,7 +46,17 @@ public function answers(): HasManyThrough

public function isLocked(): Attribute
{
return Attribute::get(fn(): bool => $this->scheduled_at !== null && $this->scheduled_at <= Carbon::now());
return Attribute::get(fn(): bool => $this->canBeScheduled() && $this->scheduled_at <= Carbon::now());
}

public function closeAt(): Attribute
{
return Attribute::get(fn(): ?Carbon => $this->canBeScheduled() ? $this->scheduled_at->copy()->addSeconds($this->duration) : null);
}

protected function canBeScheduled(): bool
{
return $this->scheduled_at !== null && $this->duration !== null;
}

public function clone(): self
Expand All @@ -61,6 +74,7 @@ public function clone(): self
public function createSubmission(User $user): QuizSubmission
{
$submission = new QuizSubmission();
$submission->closed_at = $this->closeAt;
$submission->quiz()->associate($this);
$submission->user()->associate($user);
$submission->save();
Expand Down
2 changes: 1 addition & 1 deletion app/Models/QuizSubmission.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* @property int $id
* @property Carbon $created_at
* @property Carbon $updated_at
* @property ?Carbon $closed_at
* @property Carbon $closed_at
* @property int $quiz_id
* @property int $user_id
* @property bool $isClosed
Expand Down
2 changes: 2 additions & 0 deletions database/factories/QuizFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Models\Quiz;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\Factory;
use function rand;

/**
* @extends Factory<Quiz>
Expand All @@ -17,6 +18,7 @@ public function definition(): array
{
return [
"name" => fake()->name(),
"duration" => rand(3600, 7200),
];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::table('quizzes', function (Blueprint $table) {
$table->unsignedInteger('duration')->nullable();
});
}

public function down(): void
{
Schema::table('quizzes', function (Blueprint $table) {
$table->dropColumn('duration');
});
}
};
1 change: 1 addition & 0 deletions resources/js/Types/Quiz.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface Quiz {
name: string
createdAt: number
updatedAt: number
duration?: number
locked: boolean
questions: Question[]
}
20 changes: 18 additions & 2 deletions tests/Feature/QuizTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ public function testUserCannotCreateInvalidQuiz(): void
->post("/admin/quizzes", ["name" => "correct", "scheduled_at" => "2022-01-01 01:01:01"])
->assertRedirect("/")->assertSessionHasErrors(["scheduled_at"]);

$this->from("/")
->post("/admin/quizzes", ["name" => "correct", "duration" => -100])
->assertRedirect("/")->assertSessionHasErrors(["duration"]);

$this->from("/")
->post("/admin/quizzes", ["name" => "correct", "duration" => 0])
->assertRedirect("/")->assertSessionHasErrors(["duration"]);

$this->assertDatabaseCount("quizzes", 0);
}

Expand All @@ -166,10 +174,10 @@ public function testUserCanEditQuiz(): void

$this->actingAs($this->user)
->from("/")
->patch("/admin/quizzes/{$quiz->id}", ["name" => "New quiz", "scheduled_at" => "2024-03-10 12:15:00"])
->patch("/admin/quizzes/{$quiz->id}", ["name" => "New quiz", "scheduled_at" => "2024-03-10 12:15:00", "duration" => 7200])
->assertRedirect("/");

$this->assertDatabaseHas("quizzes", ["name" => "New quiz", "scheduled_at" => "2024-03-10 12:15:00"]);
$this->assertDatabaseHas("quizzes", ["name" => "New quiz", "scheduled_at" => "2024-03-10 12:15:00", "duration" => 7200]);
}

public function testUserCannotEditQuizThatNotExisted(): void
Expand Down Expand Up @@ -201,6 +209,14 @@ public function testUserCannotMakeInvalidEdit(): void
->patch("/admin/quizzes/{$quiz->id}", ["name" => "correct", "scheduled_at" => "2022-01-01 01:01:01"])
->assertRedirect("/")->assertSessionHasErrors(["scheduled_at"]);

$this->from("/")
->patch("/admin/quizzes/{$quiz->id}", ["name" => "correct", "duration" => -100])
->assertRedirect("/")->assertSessionHasErrors(["duration"]);

$this->from("/")
->patch("/admin/quizzes/{$quiz->id}", ["name" => "correct", "duration" => 0])
->assertRedirect("/")->assertSessionHasErrors(["duration"]);

$this->assertDatabaseHas("quizzes", ["name" => "Old quiz"]);
}

Expand Down

0 comments on commit a72a06d

Please sign in to comment.