PlanTempusApp/PlanTempus.Application/Features/Customers/Components/CustomerDetailView/Default.cshtml
Janus C. H. Knudsen 1b25978d9b Adds comprehensive customer detail view components
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
2026-01-25 01:55:41 +01:00

123 lines
4.9 KiB
Text

@model PlanTempus.Application.Features.Customers.Components.CustomerDetailViewViewModel
<swp-customer-detail-view id="customer-detail-view" data-customer="@Model.CustomerId">
<!-- Sticky Header (generic from page.css) -->
<swp-sticky-header>
<swp-header-content>
<!-- Page Header with Back Button -->
<swp-page-header>
<swp-back-link href="/kunder">
<i class="ph ph-arrow-left"></i>
<span>@Model.BackText</span>
</swp-back-link>
<swp-page-actions>
<swp-btn class="secondary">
<i class="ph ph-trash"></i>
<span>@Model.DeleteButtonText</span>
</swp-btn>
<swp-btn class="primary">
<i class="ph ph-floppy-disk"></i>
<span>@Model.SaveButtonText</span>
</swp-btn>
</swp-page-actions>
</swp-page-header>
<!-- Customer Header -->
@await Component.InvokeAsync("CustomerDetailHeader", Model.CustomerId)
</swp-header-content>
<!-- Tabs (outside header-content, inside sticky-header) -->
<swp-tab-bar>
<swp-tab class="active" data-tab="overview">@Model.TabOverview</swp-tab>
<swp-tab data-tab="economy">@Model.TabEconomy</swp-tab>
<swp-tab data-tab="statistics">@Model.TabStatistics</swp-tab>
<swp-tab data-tab="journal">@Model.TabJournal</swp-tab>
<swp-tab data-tab="appointments">@Model.TabAppointments</swp-tab>
<swp-tab data-tab="giftcards">@Model.TabGiftcards</swp-tab>
<swp-tab data-tab="activity">@Model.TabActivity</swp-tab>
</swp-tab-bar>
</swp-sticky-header>
<!-- Tab Contents -->
<swp-tab-content data-tab="overview" class="active">
<swp-page-container>
@await Component.InvokeAsync("CustomerDetailOverview", Model.CustomerId)
</swp-page-container>
</swp-tab-content>
<swp-tab-content data-tab="economy">
<swp-page-container>
@await Component.InvokeAsync("CustomerDetailEconomy", Model.CustomerId)
</swp-page-container>
</swp-tab-content>
<swp-tab-content data-tab="statistics">
<swp-page-container>
@await Component.InvokeAsync("CustomerDetailStatistics", Model.CustomerId)
</swp-page-container>
</swp-tab-content>
<swp-tab-content data-tab="journal">
<swp-page-container>
@await Component.InvokeAsync("CustomerDetailJournal", Model.CustomerId)
</swp-page-container>
</swp-tab-content>
<swp-tab-content data-tab="appointments">
<swp-page-container>
@await Component.InvokeAsync("CustomerDetailAppointments", Model.CustomerId)
</swp-page-container>
</swp-tab-content>
<swp-tab-content data-tab="giftcards">
<swp-page-container>
@await Component.InvokeAsync("CustomerDetailGiftcards", Model.CustomerId)
</swp-page-container>
</swp-tab-content>
<swp-tab-content data-tab="activity">
<swp-page-container>
@await Component.InvokeAsync("CustomerDetailActivity", Model.CustomerId)
</swp-page-container>
</swp-tab-content>
</swp-customer-detail-view>
<script>
// Tab switching
document.querySelectorAll('#customer-detail-view swp-tab').forEach(tab => {
tab.addEventListener('click', () => {
const tabName = tab.dataset.tab;
const container = document.getElementById('customer-detail-view');
// Update tab active state
container.querySelectorAll('swp-tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
// Update content visibility
container.querySelectorAll('swp-tab-content').forEach(content => {
content.classList.remove('active');
if (content.dataset.tab === tabName) {
content.classList.add('active');
}
});
});
});
// Booking exclusion toggle (feature-specific)
const bookingExclusion = document.querySelector('swp-booking-exclusion');
if (bookingExclusion) {
bookingExclusion.addEventListener('click', () => {
const isExcluded = bookingExclusion.dataset.excluded === 'true';
bookingExclusion.dataset.excluded = isExcluded ? 'false' : 'true';
const icon = bookingExclusion.querySelector('.icon');
const text = bookingExclusion.querySelector('span:not(.icon)');
if (isExcluded) {
icon.className = 'ph ph-check icon';
text.textContent = 'Booking tilladt';
} else {
icon.className = 'ph ph-x icon';
text.textContent = 'Booking blokeret';
}
});
}
</script>