The DRY Approach to CRM Status Displays: Building a Universal Badge Component
Struggling with managing multiple models and their various statuses in your CRM? Learn how to leverage Enums and dynamic types to create a sleek, color-coded badge system for different statuses.


Are you wrestling with a CRM that's bursting at the seams with multiple models, each flaunting its own set of statuses? If you've ever found yourself drowning in a sea of repetitive code updates just to change a simple status display, you're in the right place. This post is your lifeline to a more efficient, maintainable solution.
Imagine a world where you can update status displays across your entire application by tweaking just one piece of code. Sounds too good to be true? Well, buckle up, because we're about to make it a reality.
In this guide, we'll dive into:
- The power of Enums and dynamic types
- Creating a sleek, color-coded badge system for different statuses
- Implementing a centralized approach to status management
//TaskStatusBadge.vue
{{ startCase(status) }}
- Limited Scope: This component is tailored for a specific set of statuses. What happens when we need to add a new status or change an existing one? We'd have to modify the component itself.
- Repetitive Code: With 5 different badge components for various models, we're violating the DRY (Don't Repeat Yourself) principle. This leads to maintenance headaches and increased chances of inconsistencies.
- Scalability Concerns: As our application grows, creating a new component for each model's statuses or types becomes unsustainable.
The Vision: A Universal Badge Component
- Accepts a :type prop to specify the current status
- Takes a :types prop to define all possible statuses and their corresponding styles
- Automatically renders the correct badge based on these props
- Use the same component for all models, reducing code duplication
- Easily add or modify statuses without touching the component's internal logic
- Ensure consistency across our entire application
The Power of Dynamic Badges: A Deep Dive
// Badge.vue
{{ startCase(type) }}
- type: The current status or type
- types: An object mapping types to their corresponding color classes
// App\Enums\ClientTypes.php
mapWithKeys(function ($case) {
return [$case->value => ucwords(str_replace('_', ' ', $case->name))];
})
->toArray();
}
public static function badgeColors()
{
return [
self::LEAD->value => 'yellow-badge',
self::PROSPECT->value => 'blue-badge',
self::CUSTOMER->value => 'green-badge',
self::INACTIVE->value => 'red-badge',
self::REFERRED->value => 'purple-badge',
self::VIP->value => 'indigo-badge'
];
}
}- It defines all possible client types, ensuring consistency across your application.
- The badgeColors() method maps each type to its corresponding color class.
/* Badge Colors */
.yellow-badge {
@apply bg-yellow-50 text-yellow-800 ring-yellow-600/20;
}
.blue-badge {
@apply bg-blue-50 text-blue-800 ring-blue-600/20;
}
/* ... other badge colors ... */- Pass ClientTypes::badgeColors() from your backend to your frontend.
- In your Vue component, pass this data to the
component:
- Centralized Management: All badge colors are defined in one place (the enum), making updates a breeze.
- Reusability: Our
component can now be used for any model with statuses or types. - Scalability: Adding new types or changing existing ones no longer requires touching the component code.
- Consistency: With colors defined in the enum, we ensure consistent styling across the application.