Adding a Kanban Board per Resource in Filament PHP
When I started building Vendex, a vendor and proposal management system, I envisioned a way to streamline the process of managing proposals. I wanted to allow the admin to visualize proposals submitted for a project in a Kanban board format. The goal? Make it easy to drag and drop proposals across various statuses and manage them with a few clicks.
Instead of starting from scratch, I decided to leverage the excellent Filament Kanban Plugin. This plugin provides a robust foundation for building Kanban boards in Filament PHP applications. However, one challenge arose: the plugin didn’t natively support adding a Kanban board per resource. For Vendex, every project had its own unique set of proposals, so I needed to extend the functionality.
Here’s how I solved this, step by step.
Creating a Custom Kanban Page
To create a Kanban board tied to a specific resource (in my case, projects), I extended the plugin’s KanbanBoard class by creating a custom Filament page:
class ProjectProposals extends KanbanBoard { protected static string $model = Proposal::class; protected static string $statusEnum = ProposalStatus::class; protected static bool $shouldRegisterNavigation = false; protected static string $view = 'filament.app.pages.proposals.kanban.kanban-board'; protected static string $headerView = 'filament.app.pages.proposals.kanban.kanban-header'; protected static string $recordView = 'filament.app.pages.proposals.kanban.kanban-record'; protected static string $statusView = 'filament.app.pages.proposals.kanban.kanban-status'; public bool $disableEditModal = true; public ?int $project_id = null; public Project $project; public Proposal $proposal; public function mount(): void { parent::mount(); $this->project = Project::where('id', $this->project_id)->firstOrFail(); } public function getTitle(): string | Htmlable { return 'Project : ' . $this->project->title; } }
Breaking It Down: Customizing the Mount Function
The mount method is one of the first things to understand. Its role is to prepare the page for rendering. Here’s the critical piece:
public function mount(): void { parent::mount(); $this->project = Project::where('id', $this->project_id)->firstOrFail(); }
At first glance, this snippet looks simple, but it’s crucial.
- parent::mount();: This ensures that any initialization logic in the parent KanbanBoard class is executed. Skipping this could break core functionality provided by the plugin.
- Fetching the project: I used the where clause to retrieve the project associated with the provided project_id. The firstOrFail() method ensures the system throws a 404 error if no matching project is found, which is a safe way to handle invalid project IDs.
- Why store the project? By storing the project in the $project variable, I could access its details throughout the class without repeatedly querying the database.
Displaying the Board Title Dynamically
To give the admin a clear context of what they’re managing, I dynamically set the board title based on the project name:
public function getTitle(): string | Htmlable { return 'Project : ' . $this->project->title; }
This line ensures that when the Kanban page is loaded, the admin sees a heading like "Project: New Office Construction" instead of a generic title.
Fetching Records for the Kanban Board
Every Kanban column needs data, and the records method is responsible for retrieving the proposals for a specific project:
protected function records(): Collection { return $this->project->proposals() ->with(['project', 'vendor', 'user']) ->ordered() ->get(); }
Handling Status Changes
Dragging a proposal from one status to another triggers the onStatusChanged method:
public function onStatusChanged(int $recordId, string $status, array $fromOrderedIds, array $toOrderedIds): void { $proposal = Proposal::find($recordId); $proposal->update(['status' => $status]); Proposal::setNewOrder($toOrderedIds); if ($status === ProposalStatus::Accepted->value) { $vendor = Vendor::find($proposal->vendor->id); Mail::to($vendor)->send(new ProposalAccepted($vendor, $proposal)); Notification::make() ->title('Mail Sent To Vendor successfully') ->success() ->send(); } Notification::make() ->title('Status Changed successfully') ->success() ->send(); }
What Happens Here?
- Status Update: When a proposal’s status changes (e.g., from Pending to Accepted), it updates the status field in the database.
- Reordering Records: The new order of proposals in the target column is saved using setNewOrder().
- Sending Notifications: If the status is set to Accepted, the system sends an email to the vendor and notifies the admin of the successful action.
Adding Routes
To make the page accessible, I added a custom route in web.php:
Route::name('filament.') ->group(function () { foreach (Filament::getPanels() as $panel) { Route::get('/project/{project_id}/proposals', ProjectProposals::class) ->name('project.proposals'); } });
This route dynamically passes the project_id to the ProjectProposals page, ensuring each project has its own unique Kanban board.
Customizing Views
The Kanban plugin allows for highly customizable views. For Vendex, I created specific views for:
- Kanban Header: Displays project details.
- Kanban Record: Custom proposal cards.
- Kanban Status: Labels like Pending, Reviewed, Accepted.
These views were registered using properties like $headerView and $recordView.
Conclusion
By extending the Mokhosh Kanban plugin, I was able to integrate a dynamic, resource-specific Kanban board into Vendex. This approach not only saved development time but also provided a flexible way to manage proposals visually.
If you’re working on a similar Filament PHP project, consider checking out the Vendex to get started. With a little customization, the possibilities are endless!
Centralize Your Reminders, Avoid Missed Deadlines
Manage reminders across teams, clients, and external partners—all from one platform.
Featured Products
Customer Portals
By providing self-service options and a seamless user experience, customer portals enhance customer satisfaction and loyalty
Partner Dashboards
Partners can monitor their contributions, track shared metrics, and access valuable insights, fostering collaboration and mutual success.
Operation Tools
It simplifies workflows and enhances productivity by providing easy access to essential tools like communication channels, and analytics.
Custom CRM
The CRM dashboard streamlines workflows, empowers sales teams with actionable insights, and enhances overall customer relationship management.
Corporate KPI Dashboard
A Corporate KPI Dashboard Solution translates complex data into real-time visual insights, enabling data-driven decision-making and performance monitoring.
Admin Panels
Admin Panels for modern organizations streamline administrative tasks by providing a centralized interface for managing data, users, and system settings efficiently.
Customer Self-Service Portal
A Customer Self-Service Portal empowers businesses to provide 24/7 support by allowing customers to access information, resolve issues, and manage their accounts independently.
Talent Management Solution
A Talent Management Solution helps organizations attract, develop, and retain top talent by streamlining recruitment, performance management, and employee development processes.
Tax & Accounting Dashboard
Tax & Accounting Software streamlines financial management for organizations, automating tax compliance, bookkeeping, and reporting processes.
AI Form & Quiz Builder
An AI Form & Quiz Builder for businesses leverages artificial intelligence to create and optimize customizable forms and quizzes, enhancing data collection, feedback accuracy, and user engagement.