Shopware 6.7 introduces several enhancements and improvements to the administration interface, making it easier than ever to customize the user experience. One common requirement for developers is to add visual indicators such as badges to product detail pages. This technical guide will walk you through the complete process of implementing a custom badge in the Shopware 6.7 admin panel.
Understanding the Shopware 6.7 Admin Architecture
Before diving into implementation, it's crucial to understand how Shopware 6.7's administration interface works. The admin panel is built on top of Vue.js and follows a component-based architecture. Product detail pages are rendered using entities that extend from the base Entity class, and they utilize the DetailPage component structure.
The key files we'll be working with include:
src/Administration/Resources/app/administration/src/module/sw-product/component/sw-product-detailsrc/Administration/Resources/app/administration/src/module/sw-product/page/sw-product-detail- Custom component registration in the module
Prerequisites and Setup
First, ensure you have Shopware 6.7 installed and running. You'll need access to the administration files and proper development environment setup. For this implementation, we'll assume you're working within a custom plugin structure.
Create a new plugin directory structure:
custom/plugins/
└── YourPlugin/
├── src/
│ └── Administration/
│ └── Resources/
│ └── app/
│ └── administration/
│ └── src/
│ └── module/
│ └── sw-product/
│ └── component/
│ └── sw-product-badge
└── YourPlugin.php
Creating the Badge Component
Let's start by creating our custom badge component. Create a new file at src/Administration/Resources/app/administration/src/module/sw-product/component/sw-product-badge/index.js:
import template from './sw-product-badge.html.twig';
export default {
name: 'sw-product-badge',
template,
props: {
product: {
type: Object,
required: true
},
badgeText: {
type: String,
default: ''
},
badgeColor: {
type: String,
default: 'var(--color-brand-primary)'
},
badgeVariant: {
type: String,
default: 'primary'
}
},
data() {
return {
isVisible: true
};
},
computed: {
badgeClasses() {
return [
'sw-product-badge',
`sw-product-badge--${this.badgeVariant}`
];
},
badgeStyle() {
return {
'--badge-color': this.badgeColor
};
}
},
methods: {
toggleVisibility() {
this.isVisible = !this.isVisible;
}
}
};
Next, create the HTML template file sw-product-badge.html.twig:
{% block sw_product_badge %}
<div class="sw-product-badge" :class="badgeClasses" :style="badgeStyle">
<span class="sw-product-badge__text">{{ badgeText }}</span>
<button
v-if="badgeVariant === 'interactive'"
@click="toggleVisibility"
class="sw-product-badge__toggle"
aria-label="Toggle badge visibility"
>
<sw-icon name="regular-eye" size="12"></sw-icon>
</button>
</div>
{% endblock %}
And the corresponding CSS file sw-product-badge.scss:
.sw-product-badge {
display: inline-flex;
align-items: center;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 600;
line-height: 1.2;
min-width: 30px;
height: 24px;
&__text {
color: var(--color-white);
text-align: center;
flex-grow: 1;
}
&__toggle {
margin-left: 4px;
background: none;
border: none;
cursor: pointer;
padding: 0;
display: flex;
align-items: center;
sw-icon {
color: var(--color-white);
}
}
&--primary {
background-color: var(--badge-color);
}
&--warning {
background-color: var(--color-warning-500);
}
&--success {
background-color: var(--color-success-500);
}
&--error {
background-color: var(--color-error-500);
}
&--info {
background-color: var(--color-info-500);
}
}
Integrating with Product Detail Page
Now we need to integrate our badge component into the product detail page. Locate the product detail page component at src/Administration/Resources/app/administration/src/module/sw-product/page/sw-product-detail/index.js and modify it:
import template from './sw-product-detail.html.twig';
import SwProductBadge from '../component/sw-product-badge';
export default {
name: 'sw-product-detail',
template,
components: {
...Shopware.Component.getComponents('sw-product-detail'),
'sw-product-badge': SwProductBadge
},
props: {
product: {
type: Object,
required: true
}
},
data() {
return {
badgeConfig: {
text: 'Special Offer',
color: '#ff6b6b',
variant: 'warning'
}
};
},
computed: {
isProductActive() {
return this.product && this.product.active;
},
showBadge() {
// Add your custom logic here
return this.isProductActive || this.product?.customFields?.showBadge;
}
}
};
Update the HTML template to include our badge:
{% block sw_product_detail %}
<div class="sw-product-detail">
<div class="sw-product-detail__header">
<h2>{{ product.translated.name }}</h2>
<sw-product-badge
v-if="showBadge"
:product="product"
:badge-text="badgeConfig.text"
:badge-color="badgeConfig.color"
:badge-variant="badgeConfig.variant"
>
</sw-product-badge>
</div>
<!-- Existing product detail content -->
<sw-card title="Product Information">
<!-- Your existing content -->
</sw-card>
</div>
{% endblock %}
Advanced Badge Configuration
For more sophisticated badge functionality, we can enhance our implementation to support dynamic configurations based on product properties:
// Enhanced badge component with dynamic logic
export default {
name: 'sw-product-badge',
template,
props: {
product: {
type: Object,
required: true
},
config: {
type: Object,
default: () => ({
text: '',
color: '#007bff',
variant: 'primary',
condition: null
})
}
},
computed: {
shouldShowBadge() {
if (!this.config.condition) {
return true;
}
// Support for complex conditions
if (typeof this.config.condition === 'function') {
return this.config.condition(this.product);
}
// Simple property-based condition
if (typeof this.config.condition === 'string') {
return this.product[this.config.condition];
}
return true;
},
badgeClasses() {
return [
'sw-product-badge',
`sw-product-badge--${this.config.variant}`
];
},
badgeStyle() {
return {
'--badge-color': this.config.color
};
}
}
};
Registering the Component
To ensure our component is properly registered, update the plugin's main file YourPlugin.php:
<?php declare(strict_types=1);
namespace YourPlugin;
use Shopware\Core\Framework\Plugin;
use Shopware\Core\Framework\Plugin\Context\ActivateContext;
use Shopware\Core\Framework\Plugin\Context\DeactivateContext;
class YourPlugin extends Plugin
{
public function activate(ActivateContext $context): void
{
// Add your activation logic here
}
public function deactivate(DeactivateContext $context): void
{
// Add your deactivation logic here
}
}
Customizing Badge Behavior
You can further customize the badge behavior by implementing different types of badges based on product attributes:
// In your product detail page component
computed: {
dynamicBadgeConfig() {
if (!this.product) return null;
// Check for special product types
if (this.product.type === 'promotion') {
return {
text: 'Promotion',
color: '#ff6b6b',
variant: 'error'
};
}
if (this.product.isNew) {
return {
text: 'New',
color: '#28a745',
variant: 'success'
};
}
if (this.product.stock < 10) {
return {
text: 'Low Stock',
color: '#ffc107',
variant: 'warning'
};
}
return null;
}
}
Performance Considerations
When implementing badges in Shopware 6.7, consider these performance best practices:
- Conditional Rendering: Only render badges when necessary using computed properties
- Component Caching: Implement proper caching mechanisms for frequently accessed data
- Lazy Loading: Load badge configurations only when needed
- Memory Management: Ensure proper cleanup of event listeners and references
Testing Your Implementation
Create a test file to verify your badge implementation works correctly:
// Test component integration
describe('sw-product-badge', () => {
it('should render badge with correct text', () => {
const wrapper = shallowMount(SwProductBadge, {
propsData: {
product: { id: 'test' },
badgeText: 'Test Badge'
}
});
expect(wrapper.find('.sw-product-badge__text').text()).toBe('Test Badge');
});
it('should apply correct color styling', () => {
const wrapper = shallowMount(SwProductBadge, {
propsData: {
product: { id: 'test' },
badgeText: 'Test',
badgeColor: '#ff0000'
}
});
expect(wrapper.vm.badgeStyle['--badge-color']).toBe('#ff0000');
});
});
Conclusion
Adding badges to the Shopware 6.7 admin product detail page is a straightforward yet powerful way to enhance user experience and provide visual cues about product status or special attributes. This implementation leverages Shopware's component architecture while maintaining performance standards.
The key takeaways from this implementation include:
- Proper component structure following Shopware 6.7 conventions
- Dynamic badge configuration based on product properties
- Performance optimization through conditional rendering
- Extensible design that can accommodate various badge types
- Integration with existing admin components without breaking changes
This approach ensures your custom badges will work seamlessly within the Shopware 6.7 ecosystem and provide valuable visual feedback to administrators while maintaining the platform's integrity and performance standards.
Remember to test thoroughly in different scenarios and consider edge cases where product data might be incomplete or null, ensuring your implementation gracefully handles these situations without breaking the admin interface.