Implements full customer detail page with multiple feature-rich components including overview, economy, statistics, journal, appointments, giftcards, and activity sections Creates reusable ViewComponents for different customer detail aspects with robust data modeling and presentation logic
83 lines
3.2 KiB
Text
83 lines
3.2 KiB
Text
@model PlanTempus.Application.Features.Customers.Components.CustomerDetailActivityViewModel
|
|
|
|
<!-- Filters -->
|
|
<swp-activity-filters>
|
|
@foreach (var filter in Model.Filters)
|
|
{
|
|
<swp-activity-filter class="@(filter.IsActive ? "active" : "")" data-type="@(filter.Type ?? "all")">
|
|
@if (!string.IsNullOrEmpty(filter.Icon))
|
|
{
|
|
<i class="ph ph-@filter.Icon"></i>
|
|
}
|
|
@filter.Label
|
|
</swp-activity-filter>
|
|
}
|
|
</swp-activity-filters>
|
|
|
|
<swp-card>
|
|
<swp-activity-timeline>
|
|
@foreach (var dateGroup in Model.DateGroups)
|
|
{
|
|
<swp-activity-date-group>
|
|
<swp-activity-date-header>@dateGroup.DateHeader</swp-activity-date-header>
|
|
|
|
@foreach (var item in dateGroup.Items)
|
|
{
|
|
<swp-activity-item data-type="@item.Type">
|
|
<swp-activity-icon class="@item.Type"><i class="ph ph-@item.Icon"></i></swp-activity-icon>
|
|
<swp-activity-content>
|
|
<swp-activity-title>
|
|
@Html.Raw(item.Title)
|
|
@foreach (var badge in item.Badges)
|
|
{
|
|
<swp-activity-badge class="@badge.CssClass">@badge.Text</swp-activity-badge>
|
|
}
|
|
</swp-activity-title>
|
|
<swp-activity-meta>
|
|
<swp-activity-time>@item.Time</swp-activity-time>
|
|
@if (!string.IsNullOrEmpty(item.Actor))
|
|
{
|
|
<swp-activity-actor>@item.Actor</swp-activity-actor>
|
|
}
|
|
</swp-activity-meta>
|
|
</swp-activity-content>
|
|
</swp-activity-item>
|
|
}
|
|
</swp-activity-date-group>
|
|
}
|
|
</swp-activity-timeline>
|
|
</swp-card>
|
|
|
|
<script>
|
|
(function() {
|
|
const filters = document.querySelectorAll('swp-activity-filter');
|
|
const timeline = document.querySelector('swp-activity-timeline');
|
|
|
|
filters.forEach(filter => {
|
|
filter.addEventListener('click', () => {
|
|
// Update active state
|
|
filters.forEach(f => f.classList.remove('active'));
|
|
filter.classList.add('active');
|
|
|
|
const filterType = filter.dataset.type;
|
|
|
|
// Filter items
|
|
const items = timeline.querySelectorAll('swp-activity-item');
|
|
items.forEach(item => {
|
|
if (filterType === 'all' || item.dataset.type === filterType) {
|
|
item.style.display = '';
|
|
} else {
|
|
item.style.display = 'none';
|
|
}
|
|
});
|
|
|
|
// Hide date groups with no visible items
|
|
const dateGroups = timeline.querySelectorAll('swp-activity-date-group');
|
|
dateGroups.forEach(group => {
|
|
const visibleItems = group.querySelectorAll('swp-activity-item:not([style*="display: none"])');
|
|
group.style.display = visibleItems.length > 0 ? '' : 'none';
|
|
});
|
|
});
|
|
});
|
|
})();
|
|
</script>
|