laravel new gudang-cerita-filament
git init
git add .
git commit -m "master"
git reset --hard
git clean -fd
composer require filament/filament:"~4.0"
php artisan filament:install --panels
php artisan make:filament-user
php artisan make:model story -m
<?php
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::create('stories', function (Blueprint $table) {
$table->id();
$table->string('title', 100);
$table->text('story_content');
$table->string('status')->default('waiting for review'); // waiting for review, in review, approved, canceled, rework
$table->foreignId('author_id')->constrained('users')->onDelete('cascade');
$table->foreignId('reviewer_id')->nullable()->constrained('users')->onDelete('set null');
$table->text('feedback')->nullable();
$table->softDeletes();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('stories');
}
};
composer require althinect/filament-spatie-roles-permissions
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
->plugin(FilamentSpatieRolesPermissionsPlugin::make())
php artisan vendor:publish --tag="filament-spatie-roles-permissions-config" --force
use HasRoles;
php artisan make:filament-resource User --generate --soft-deletes --view
Select::make('roles')->multiple()->relationship('roles', 'name')
php artisan make:policy
PermissionPolicy
Permission
php artisan make:policy
RolePolicy
Role
Gate::policy(Role::class, RolePolicy::class);
Gate::policy(Permission::class, PermissionPolicy::class);
php artisan make:filament-resource Story --generate --soft-deletes --view
php artisan make:observer
StoryObserver
Story
<?php
namespace App\Observers;
use App\Models\Story;
class StoryObserver
{
public function creating(Story $story): void
{
$story->author_id = auth()->id();
}
/**
* Handle the Story "created" event.
*/
public function created(Story $story): void
{
//
}
/**
* Handle the Story "updated" event.
*/
public function updated(Story $story): void
{
//
}
/**
* Handle the Story "deleted" event.
*/
public function deleted(Story $story): void
{
//
}
/**
* Handle the Story "restored" event.
*/
public function restored(Story $story): void
{
//
}
/**
* Handle the Story "force deleted" event.
*/
public function forceDeleted(Story $story): void
{
//
}
}
<?php
namespace App\Models;
use App\Observers\StoryObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
#[ObservedBy(StoryObserver::class)]
class story extends Model
{
use SoftDeletes;
//
}
php artisan make:policy
StoryPolicy
Story
// buat tab di liststory
<?php
namespace App\Filament\Resources\StoryResource\Pages;
use Filament\Actions;
use Filament\Resources\Components\Tab;
use Illuminate\Database\Eloquent\Builder;
use App\Filament\Resources\StoryResource;
use Filament\Resources\Pages\ListRecords;
class ListStories extends ListRecords
{
protected static string $resource = StoryResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
// tambahkan pilihan tab di atas tabel list story
public function getTabs(): array
{
return [
'all' => Tab::make(),
'waiting for review' => Tab::make()
->modifyQueryUsing(fn(Builder $query) => $query->where('status', 'waiting for review')),
'in review' => Tab::make()
->modifyQueryUsing(fn(Builder $query) => $query->where('status', 'in review')),
'approved' => Tab::make()
->modifyQueryUsing(fn(Builder $query) => $query->where('status', 'in approved')),
'canceled' => Tab::make()
->modifyQueryUsing(fn(Builder $query) => $query->where('status', 'in canceled')),
'rework' => Tab::make()
->modifyQueryUsing(fn(Builder $query) => $query->where('status', 'in rework')),
];
}
}
php artisan make:filament-widget StoryStatsOverview --stats-overview
<?php
namespace App\Filament\Widgets;
use App\Models\story;
use Filament\Widgets\StatsOverviewWidget as BaseWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
class StoryStatsOverview extends BaseWidget
{
protected function getStats(): array
{
// menampilkan widget overview berdasarkan login (jika admin menampilkan semua data)
// waiting for review, in review, approved, canceled, rework
return [
Stat::make('Waiting for Review', story::where('status', 'waiting for review')->when(auth()->user()->hasRole('Writer'), function ($query) {
$query->where('author_id', auth()->user()->id);
})->count()),
Stat::make('In Review', story::where('status', 'in review')->when(auth()->user()->hasRole('Writer'), function ($query) {
$query->where('author_id', auth()->user()->id);
})->count()),
Stat::make('Approved', story::where('status', 'approved')->when(auth()->user()->hasRole('Writer'), function ($query) {
$query->where('author_id', auth()->user()->id);
})->count()),
Stat::make('Canceled', story::where('status', 'canceled')->when(auth()->user()->hasRole('Writer'), function ($query) {
$query->where('author_id', auth()->user()->id);
})->count()),
Stat::make('Rework', story::where('status', 'rework')->when(auth()->user()->hasRole('Writer'), function ($query) {
$query->where('author_id', auth()->user()->id);
})->count()),
];
}
}
php artisan make:policy
UserPolicy
User