Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions app/Enums/PostStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace App\Enums;

enum PostStatus: string
{
case Draft = 'draft';
case Published = 'published';

public function label(): string
{
return match ($this) {
self::Draft => __('posts.status.Draft'),
self::Published => __('posts.status.Published'),
};
}

public function color(): string
{
return match ($this) {
self::Draft => 'bg-yellow-500',
self::Published => 'bg-green-500',
};
}

public function badgeColor(): string
{
return match ($this) {
self::Draft => 'yellow',
self::Published => 'green',
};
}
}
3 changes: 3 additions & 0 deletions app/Http/Controllers/PostController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use App\Models\Post;
use App\Support\QueryResolver;
use App\Support\Settings;
use App\Enums\PostStatus;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
Expand Down Expand Up @@ -44,6 +45,7 @@ public function create(): View
return view('posts.create', [
'categories' => Category::query()->pluck('title', 'id'),
'tags' => Settings::getTags(),
'statuses' => PostStatus::cases(),
]);
}

Expand Down Expand Up @@ -77,6 +79,7 @@ public function edit(Post $post): View
'post' => $post,
'categories' => Category::query()->pluck('title', 'id'),
'tags' => Settings::getTags(),
'statuses' => PostStatus::cases(),
]);
}

Expand Down
3 changes: 3 additions & 0 deletions app/Http/Requests/StorePostRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

namespace App\Http\Requests;

use App\Enums\PostStatus;
use App\Traits\HasFileFromUrl;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
use Override;

final class StorePostRequest extends FormRequest
Expand Down Expand Up @@ -35,6 +37,7 @@ public function rules(): array
'image' => ['required', 'image'],
'content' => ['required'],
'published_at' => ['nullable', 'date'],
'status' => ['required', 'string', new Enum(PostStatus::class)],
'category_id' => [
'required',
'exists:categories,id',
Expand Down
4 changes: 4 additions & 0 deletions app/Models/Post.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Storage;
use Mews\Purifier\Casts\CleanHtmlInput;
use App\Enums\PostStatus;
use Override;

/**
Expand All @@ -30,6 +31,7 @@
* @property UploadedFile|string|null $image
* @property string $content
* @property Carbon|null $published_at
* @property PostStatus $status
* @property int $category_id
* @property array<string>|null $tags
* @property FeaturedStatus $is_featured
Expand All @@ -48,6 +50,7 @@
'image',
'content',
'published_at',
'status',
'category_id',
'tags',
'is_featured',
Expand Down Expand Up @@ -125,6 +128,7 @@ protected function casts(): array
'published_at' => 'datetime',
'is_featured' => FeaturedStatus::class,
'content' => CleanHtmlInput::class,
'status' => PostStatus::class,
];
}
}
1 change: 1 addition & 0 deletions database/factories/PostFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public function definition(): array
'image' => $this->fakeImageUrl(),
'content' => $this->faker->randomHtml(),
'published_at' => $this->faker->dateTimeBetween('-1 month', '+3 months'),
'status' => $this->faker->randomElement(array_column(PostStatus::cases(), 'value')),
'category_id' => CategoryFactory::new(),
'tags' => $this->faker->randomElements(['Eloquent', 'Blade', 'Migrations', 'Seeding', 'Routing', 'Controllers', 'Middleware', 'Requests', 'Responses', 'Views', 'Forms', 'Validation', 'Mail', 'Notifications'], $this->faker->numberBetween(1, 3)),
'is_featured' => $this->faker->randomElement(array_column(FeaturedStatus::cases(), 'value')),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

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

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('posts', function (Blueprint $table): void {
$table->string('status')->default('draft')->after('published_at');
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
// did not prefer to add down method, I just add another migration if i want to rollback
}
};
6 changes: 6 additions & 0 deletions lang/ar/posts.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
'Image' => 'الصورة',
'Category' => 'التصنيف',
'Select a Category' => 'اختر التصنيف',
'Status' => 'الحالة',
'Select a Status' => 'اختر الحالة',
'Description' => 'الوصف',
'Tags' => 'الوسوم',
'Featured' => 'مميز',
Expand All @@ -29,6 +31,10 @@
'Update Post' => 'تعديل المقال',
'Cancel' => 'إلغاء',
],
'status' => [
'Draft' => 'مسودة',
'Published' => 'منشور',
],
'show' => [
'Not Featured' => 'غير مميز',
'Featured' => 'مميز',
Expand Down
6 changes: 6 additions & 0 deletions lang/en/posts.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
'Image' => 'Image',
'Category' => 'Category',
'Select a Category' => 'Select a Category',
'Status' => 'Status',
'Select a Status' => 'Select a Status',
'Description' => 'Description',
'Tags' => 'Tags',
'Featured' => 'Featured',
Expand All @@ -29,6 +31,10 @@
'Update Post' => 'Update Post',
'Cancel' => 'Cancel',
],
'status' => [
'Draft' => 'Draft',
'Published' => 'Published',
],
'show' => [
'Not Featured' => 'Not Featured',
'Featured' => 'Featured',
Expand Down
6 changes: 6 additions & 0 deletions lang/fr/posts.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
'Image' => 'Image',
'Category' => 'Catégorie',
'Select a Category' => 'Sélectionnez une catégorie',
'Status' => 'Statut',
'Select a Status' => 'Sélectionnez un statut',
'Description' => 'Description',
'Tags' => 'Tags',
'Featured' => 'En vedette',
Expand All @@ -29,6 +31,10 @@
'Update Post' => 'Mettre à jour l\'article',
'Cancel' => 'Annuler',
],
'status' => [
'Draft' => 'Brouillon',
'Published' => 'Publié',
],
'show' => [
'Not Featured' => 'Pas en vedette',
'Featured' => 'En vedette',
Expand Down
6 changes: 6 additions & 0 deletions lang/gu/posts.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
'Image' => 'છબી',
'Category' => 'વર્ગ',
'Select a Category' => 'એક વર્ગ પસંદ કરો',
'Status' => 'સ્થિતિ',
'Select a Status' => 'એક સ્થિતિ પસંદ કરો',
'Description' => 'વર્ણન',
'Tags' => 'ટેગ્સ',
'Featured' => 'ફિચર્ડ',
Expand All @@ -30,6 +32,10 @@
'Update Post' => 'પોસ્ટ અપડેટ કરો',
'Cancel' => 'રદ કરો',
],
'status' => [
'Draft' => 'ડ્રાફ્ટ',
'Published' => 'પ્રકાશિત',
],
'show' => [
'Not Featured' => 'ફિચર્ડ નથી',
'Featured' => 'ફિચર્ડ',
Expand Down
6 changes: 6 additions & 0 deletions lang/hi/posts.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
'Update Post' => 'पोस्ट अपडेट करें',
'Cancel' => 'रद करना',
],
'status' => [
'Draft' => 'मसौदा',
'Published' => 'प्रकाशित',
],
'show' => [
'Not Featured' => 'विशेष रुप से प्रदर्शित नहीं',
'Featured' => 'विशेष रुप से प्रदर्शित',
Expand All @@ -51,4 +55,6 @@
'Post featured successfully' => 'पोस्ट सफलतापूर्वक विशेष रुप से प्रदर्शित की गई।',
'Post unfeatured successfully' => 'पोस्ट सफलतापूर्वक विशेष रुप से प्रदर्शित नहीं की गई।',
],
];
],
];
14 changes: 14 additions & 0 deletions resources/views/posts/_form.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@
<h2 class="text-base font-semibold text-stone-950">Publishing</h2>

<div class="mt-6 space-y-5">
<x-field>
<x-label for="status">{{ __('posts.form.Status') }}</x-label>
<x-select id="status" name="status">
<option value="">{{ __('posts.form.Select a Status') }}</option>
@foreach ($statuses as $status)
<option value="{{ $status->value }}" @selected(old('status', $post->status?->value ?? null) == $status->value)>
{{ $status->label() }}
</option>
@endforeach
</x-select>
@error('status')
<x-error-message>{{ $message }}</x-error-message>
@enderror
</x-field>
<x-field>
<x-label for="category_id">{{ __('posts.form.Category') }}</x-label>
<x-select id="category_id" name="category_id">
Expand Down
6 changes: 6 additions & 0 deletions tests/Feature/Http/Controllers/PostControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Tests\Feature;

use App\Enums\PostStatus;
use App\Models\Category;
use App\Models\Post;
use Illuminate\Http\UploadedFile;
Expand Down Expand Up @@ -111,6 +112,7 @@
->assertViewHasAll([
'categories',
'tags',
'statuses',
]);
});

Expand All @@ -125,6 +127,7 @@
'category_id' => $category->id,
'description' => 'this is the description',
'content' => 'this is the content',
'status' => PostStatus::Draft->value,
'tags' => ['Eloquent'],
])
->assertRedirect(route('posts.index', ['published' => true]))
Expand All @@ -144,6 +147,7 @@
'category_id',
'description',
'content',
'status',
]);
});

Expand All @@ -168,6 +172,7 @@
'post',
'categories',
'tags',
'statuses',
]);
});

Expand All @@ -186,6 +191,7 @@
'category_id' => $CategoryId,
'description' => 'this is the description',
'content' => 'this is the content',
'status' => PostStatus::Published->value,
'tags' => ['Eloquent'],
])
->assertRedirect(route('posts.index', ['sortBy' => 'title', 'direction' => 'asc']))
Expand Down
61 changes: 61 additions & 0 deletions tests/Unit/Enums/PostStatusTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

use App\Enums\PostStatus;

it('returns the correct label for Draft', function (): void {
$status = PostStatus::Draft;
$label = $status->label();

expect($label)->toBe(__('posts.status.Draft'));
});

it('returns the correct label for Published', function (): void {
$status = PostStatus::Published;
$label = $status->label();

expect($label)->toBe(__('posts.status.Published'));
});

it('returns the correct color for Draft', function (): void {
$status = PostStatus::Draft;
$color = $status->color();

expect($color)->toBe('bg-yellow-500');
});

it('returns the correct color for Published', function (): void {
$status = PostStatus::Published;
$color = $status->color();

expect($color)->toBe('bg-green-500');
});

it('returns the correct badge color for Draft', function (): void {
$status = PostStatus::Draft;
$badgeColor = $status->badgeColor();

expect($badgeColor)->toBe('yellow');
});

it('returns the correct badge color for Published', function (): void {
$status = PostStatus::Published;
$badgeColor = $status->badgeColor();

expect($badgeColor)->toBe('green');
});

it('returns the correct badge color', function (string $value, string $expected): void {
expect(PostStatus::tryFrom($value)?->badgeColor())->toBe($expected);
})
->with([
PostStatus::Draft->name => [
'value' => PostStatus::Draft->value,
'expected' => 'yellow',
],
PostStatus::Published->name => [
'value' => PostStatus::Published->value,
'expected' => 'green',
],
]);