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
This commit is contained in:
Janus C. H. Knudsen 2026-01-25 01:55:41 +01:00
parent 38e9243bcd
commit 1b25978d9b
26 changed files with 3792 additions and 956 deletions

View file

@ -0,0 +1,201 @@
@model PlanTempus.Application.Features.Customers.Components.CustomerDetailOverviewViewModel
<swp-detail-grid>
<!-- Left Column -->
<swp-card-column>
<!-- Kontaktoplysninger -->
<swp-card>
<swp-card-header>
<swp-card-title>
<i class="ph ph-address-book"></i>
<span>@Model.ContactTitle</span>
</swp-card-title>
</swp-card-header>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>@Model.PhoneLabel</swp-edit-label>
<swp-edit-value contenteditable="true">@Model.Phone</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>@Model.EmailLabel</swp-edit-label>
<swp-edit-value contenteditable="true">@Model.Email</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>@Model.AddressLabel</swp-edit-label>
<swp-edit-value contenteditable="true">@Model.Address</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>@Model.ZipCityLabel</swp-edit-label>
<swp-edit-value contenteditable="true">@Model.ZipCity</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
</swp-card>
<!-- Profil -->
<swp-card>
<swp-card-header>
<swp-card-title>
<i class="ph ph-user-circle"></i>
<span>@Model.ProfileTitle</span>
</swp-card-title>
</swp-card-header>
<swp-profile-boxes>
@foreach (var item in Model.ProfileItems)
{
<swp-profile-box>
<swp-profile-box-label>@item.Title</swp-profile-box-label>
<swp-profile-box-value>@item.Value</swp-profile-box-value>
</swp-profile-box>
}
</swp-profile-boxes>
</swp-card>
</swp-card-column>
<!-- Right Column -->
<swp-card-column>
<!-- Marketing -->
<swp-card>
<swp-card-header>
<swp-card-title>
<i class="ph ph-megaphone"></i>
<span>@Model.MarketingTitle</span>
</swp-card-title>
</swp-card-header>
<swp-toggle-row>
<swp-toggle-label>@Model.EmailMarketingLabel</swp-toggle-label>
<swp-toggle-slider data-value="@(Model.EmailOptIn ? "yes" : "no")">
<swp-toggle-option>@Model.YesLabel</swp-toggle-option>
<swp-toggle-option>@Model.NoLabel</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
<swp-toggle-row>
<swp-toggle-label>@Model.SmsMarketingLabel</swp-toggle-label>
<swp-toggle-slider data-value="@(Model.SmsOptIn ? "yes" : "no")">
<swp-toggle-option>@Model.YesLabel</swp-toggle-option>
<swp-toggle-option>@Model.NoLabel</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
</swp-card>
<!-- Betalingsindstillinger -->
<swp-card>
<swp-card-header>
<swp-card-title>
<i class="ph ph-credit-card"></i>
<span>@Model.PaymentTitle</span>
</swp-card-title>
</swp-card-header>
<swp-toggle-row>
<swp-toggle-info>
<swp-toggle-label>@Model.RequirePrepaymentLabel</swp-toggle-label>
<swp-toggle-desc>@Model.RequirePrepaymentDesc</swp-toggle-desc>
</swp-toggle-info>
<swp-toggle-slider data-value="@(Model.RequirePrepayment ? "yes" : "no")">
<swp-toggle-option>@Model.YesLabel</swp-toggle-option>
<swp-toggle-option>@Model.NoLabel</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
<swp-toggle-row>
<swp-toggle-info>
<swp-toggle-label>@Model.AllowPartialPaymentLabel</swp-toggle-label>
<swp-toggle-desc>@Model.AllowPartialPaymentDesc</swp-toggle-desc>
</swp-toggle-info>
<swp-toggle-slider data-value="@(Model.AllowPartialPayment ? "yes" : "no")">
<swp-toggle-option>@Model.YesLabel</swp-toggle-option>
<swp-toggle-option>@Model.NoLabel</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
</swp-card>
<!-- Praeferencer -->
<swp-card>
<swp-card-header>
<swp-card-title>
<i class="ph ph-sliders-horizontal"></i>
<span>@Model.PreferencesTitle</span>
</swp-card-title>
</swp-card-header>
<swp-profile-boxes>
<swp-profile-box>
<swp-profile-box-label>@Model.PreferredHairdresserLabel</swp-profile-box-label>
<swp-profile-box-value>@Model.PreferredHairdresser</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box>
<swp-profile-box-label>@Model.PreferredDaysLabel</swp-profile-box-label>
<swp-profile-box-value>@Model.PreferredDays</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box class="full-width">
<swp-profile-box-label>@Model.SpecialRequestsLabel</swp-profile-box-label>
<swp-profile-box-value>@Model.SpecialRequests</swp-profile-box-value>
</swp-profile-box>
</swp-profile-boxes>
</swp-card>
<!-- Advarsler -->
<swp-card>
<swp-card-header>
<swp-card-title>
<i class="ph ph-warning"></i>
<span>@Model.WarningsTitle</span>
</swp-card-title>
</swp-card-header>
<swp-profile-boxes>
@foreach (var warning in Model.Warnings)
{
<swp-profile-box class="warning full-width">
<swp-profile-box-label>@warning.Title</swp-profile-box-label>
<swp-profile-box-value>@warning.Value</swp-profile-box-value>
</swp-profile-box>
}
</swp-profile-boxes>
</swp-card>
<!-- Kundegruppe & Relationer -->
<swp-card>
<swp-card-header>
<swp-card-title>
<i class="ph ph-users-three"></i>
<span>@Model.GroupRelationsTitle</span>
</swp-card-title>
</swp-card-header>
<swp-customer-group-row>
<swp-customer-group-label>@Model.GroupLabel</swp-customer-group-label>
<swp-select>
<button type="button">
<swp-select-value>@Model.GroupName</swp-select-value>
<i class="ph ph-caret-down"></i>
</button>
<swp-select-dropdown>
<swp-select-option class="@(Model.GroupId == "standard" ? "selected" : "")" data-value="standard">Standard</swp-select-option>
<swp-select-option class="@(Model.GroupId == "premium" ? "selected" : "")" data-value="premium">Premium</swp-select-option>
<swp-select-option class="@(Model.GroupId == "erhverv" ? "selected" : "")" data-value="erhverv">Erhverv</swp-select-option>
<swp-select-option class="@(Model.GroupId == "medarbejder" ? "selected" : "")" data-value="medarbejder">Medarbejder</swp-select-option>
<swp-select-option class="@(Model.GroupId == "familie" ? "selected" : "")" data-value="familie">Familie & Venner</swp-select-option>
</swp-select-dropdown>
</swp-select>
</swp-customer-group-row>
<swp-relations-list>
@foreach (var relation in Model.Relations)
{
<swp-relation-item>
<swp-relation-avatar>@relation.Initials</swp-relation-avatar>
<swp-relation-info>
<swp-relation-name>@relation.Name</swp-relation-name>
<swp-relation-type>@relation.Type</swp-relation-type>
</swp-relation-info>
<swp-relation-actions>
<swp-relation-link>Abn</swp-relation-link>
<swp-relation-remove>&times;</swp-relation-remove>
</swp-relation-actions>
</swp-relation-item>
}
<swp-add-relation>
<i class="ph ph-plus"></i>
<span>@Model.AddRelationText</span>
</swp-add-relation>
</swp-relations-list>
</swp-card>
</swp-card-column>
</swp-detail-grid>