Courses

Creating CRM with Filament 3: Step-By-Step

Pipeline Stages Resource: Reorderable

You're reading a FREE PREVIEW of a PREMIUM course.
Summary of this lesson:
- Creating PipelineStage model with position and default flags
- Implementing table reordering functionality
- Adding "Set Default" action with confirmation
- Creating automatic position assignment for new stages
- Adding pipeline stage selection to Customer resource

Link to the repository

[Only for premium members]

Next up, each of our Customers has to go in a Pipeline to advance from one status to another. For example, we start at Contact Made and then progress to Meeting Scheduled. To do this, we need to create a new resource Pipeline Stages:

In this lesson, we will:

  • Create pipeline_stages DB structure: Model/Migration and a hasMany relationship to customers
  • Create Seeds with semi-real data without factories
  • Create a Filament Resource for Pipeline Stages
  • Auto-assign the new position to a new Pipeline Stage
  • Make the table reorderable with the position field
  • Add a Custom Action Set Default with confirmation
  • Add a DeleteAction to the table with validation if that record is used
  • Add pipeline stage information to the Customer Resource table/form

Creating Pipeline Stages Database

These are the fields for our DB:

  • id
  • name
  • position - Order of the stages
  • is_default

This will be seeded by default workflow but can be changed by admins to suit their needs.

Let's start with our migration:

Migration

Schema::create('pipeline_stages', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->integer('position');
$table->boolean('is_default')->default(false);
$table->timestamps();
});

Then, we need to create a model:

app/Models/PipelineStage.php

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
 
class PipelineStage extends Model
{
protected $fillable = [
'name',
'position',
'is_default',
];
 
public function customers(): HasMany
{
return $this->hasMany(Customer::class);
}
}

Next, we will make sure that we have some Default data in our database:

database/seeders/DatabaseSeeder.php

public function run(): void
{
User::factory()->create([
'name' => 'Test Admin',
'email' => '[email protected]',
]);
 
Customer::factory()
->count(10)
->create();
 
$leadSources = [
'Website',
'Online AD',
'Twitter',
'LinkedIn',
'Webinar',
'Trade Show',
'Referral',
];
 
foreach ($leadSources as $leadSource) {
LeadSource::create(['name' => $leadSource]);
}
 
$tags = [
'Priority',
'VIP'
];
 
foreach ($tags as $tag) {
Tag::create(['name' => $tag]);
}
 
$pipelineStages = [
[
'name' => 'Lead',
'position' => 1,
'is_default' => true,
],
[
'name' => 'Contact Made',
'position' => 2,
],
[
'name' => 'Proposal Made',
'position' => 3,
],
[
'name' => 'Proposal Rejected',
'position' => 4,
],
[
'name' => 'Customer',
'position' => 5,
]
];
 
foreach ($pipelineStages as $stage) {
PipelineStage::create($stage);
}
 
$defaultPipelineStage = PipelineStage::where('is_default', true)->first()->id;
Customer::factory()->count(10)->create([
'pipeline_stage_id' => $defaultPipelineStage,
]);
}

One thing to note here is that we have...

The full lesson is only for Premium Members.
Want to access all 17 text lessons of this course? (97 min read)

You also get:

  • 77 courses
  • Premium tutorials
  • Access to repositories
  • Private Discord