PlanTempusApp/PlanTempus.Application/Features/Customers/Pages/Index.cshtml
Janus C. H. Knudsen 38e9243bcd Adds create customer drawer to customers page
Implements new drawer for creating customers with form inputs for contact details and notes

Enhances customer management by providing a streamlined way to add new customer records directly from the customers index page
2026-01-24 10:59:21 +01:00

309 lines
14 KiB
Text

@page "/kunder"
@model PlanTempus.Application.Features.Customers.Pages.IndexModel
@{
ViewData["Title"] = "Kunder";
}
<swp-sticky-header>
<swp-header-content>
<swp-page-header>
<swp-page-title>
<h1 localize="customers.title">Kunder</h1>
<p localize="customers.subtitle">Administrer kunder og kundekort</p>
</swp-page-title>
</swp-page-header>
<swp-stats-row>
<swp-stat-card class="highlight">
<swp-stat-value>12</swp-stat-value>
<swp-stat-label localize="customers.stats.total">Total kunder</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value>3</swp-stat-value>
<swp-stat-label localize="customers.stats.newThisMonth">Nye denne måned</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value>12,4</swp-stat-value>
<swp-stat-label localize="customers.stats.avgVisits">Gns. besøg</swp-stat-label>
</swp-stat-card>
</swp-stats-row>
</swp-header-content>
</swp-sticky-header>
<swp-page-container>
@await Component.InvokeAsync("CustomerTable")
</swp-page-container>
<!-- Customer Drawer -->
<div id="customer-drawer" data-drawer="xxl" data-customer-id="">
<swp-drawer-header>
<swp-drawer-title>
<i class="ph ph-user"></i>
<span localize="customers.drawer.title">Kundekort</span>
</swp-drawer-title>
<swp-drawer-actions>
<a href="#" id="openFullDetailLink" class="drawer-detail-link">
<i class="ph ph-arrow-square-out"></i>
<span>Åbn fuld side</span>
</a>
<swp-drawer-close data-drawer-close>
<i class="ph ph-x"></i>
</swp-drawer-close>
</swp-drawer-actions>
</swp-drawer-header>
<swp-drawer-body>
<!-- Customer Header -->
<swp-customer-header>
<swp-customer-avatar-large id="drawerAvatar">SN</swp-customer-avatar-large>
<swp-customer-header-info>
<swp-customer-header-top>
<swp-customer-header-left>
<swp-customer-header-name id="drawerName">Sofie Nielsen</swp-customer-header-name>
<swp-customer-since id="drawerSince">Kunde siden marts 2024</swp-customer-since>
</swp-customer-header-left>
<swp-customer-header-contact>
<a href="tel:+4523456789" id="drawerPhoneLink">+45 23 45 67 89</a>
<a href="mailto:sofie@email.dk" id="drawerEmailLink">sofie@email.dk</a>
<swp-customer-tags id="drawerTags"></swp-customer-tags>
</swp-customer-header-contact>
</swp-customer-header-top>
</swp-customer-header-info>
</swp-customer-header>
<!-- Quick Stats -->
<swp-quick-stats class="cols-3">
<swp-quick-stat>
<swp-stat-value id="drawerVisits">14</swp-stat-value>
<swp-stat-label localize="customers.drawer.visits">Besøg</swp-stat-label>
</swp-quick-stat>
<swp-quick-stat>
<swp-stat-value id="drawerInterval">32 dage</swp-stat-value>
<swp-stat-label localize="customers.drawer.avgInterval">Gns. interval</swp-stat-label>
</swp-quick-stat>
<swp-quick-stat>
<swp-stat-value id="drawerHairdresser">Emma L.</swp-stat-value>
<swp-stat-label localize="customers.drawer.preferredHairdresser">Foretrukken frisør</swp-stat-label>
</swp-quick-stat>
</swp-quick-stats>
<!-- Contact Info (Editable) -->
<div>
<swp-section-label localize="customers.drawer.contactInfo">Kontaktoplysninger</swp-section-label>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label localize="customers.drawer.phone">Telefon</swp-edit-label>
<swp-edit-input><input type="tel" id="editPhone" value="+45 23 45 67 89"></swp-edit-input>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label localize="customers.drawer.email">Email</swp-edit-label>
<swp-edit-input><input type="email" id="editEmail" value="sofie@email.dk"></swp-edit-input>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label localize="customers.drawer.address">Adresse</swp-edit-label>
<swp-edit-input><input type="text" id="editAddress" value="Hovedgaden 12"></swp-edit-input>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label localize="customers.drawer.zipCity">Postnr + By</swp-edit-label>
<swp-edit-input>
<input type="text" id="editZip" value="2100" class="short">
<input type="text" id="editCity" value="København Ø">
</swp-edit-input>
</swp-edit-row>
</swp-edit-section>
</div>
<!-- Marketing Opt-in -->
<div>
<swp-section-label localize="customers.drawer.marketing">Marketing</swp-section-label>
<swp-marketing-section>
<swp-toggle-row>
<swp-toggle-label localize="customers.drawer.emailMarketing">Email marketing</swp-toggle-label>
<swp-toggle-slider id="toggleEmail" data-value="yes">
<swp-toggle-option localize="common.yes">Ja</swp-toggle-option>
<swp-toggle-option localize="common.no">Nej</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
<swp-toggle-row>
<swp-toggle-label localize="customers.drawer.smsMarketing">SMS marketing</swp-toggle-label>
<swp-toggle-slider id="toggleSms" data-value="no">
<swp-toggle-option localize="common.yes">Ja</swp-toggle-option>
<swp-toggle-option localize="common.no">Nej</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
</swp-marketing-section>
</div>
<!-- Profile Boxes -->
<div>
<swp-section-label localize="customers.drawer.profile">Profil</swp-section-label>
<swp-profile-boxes>
<swp-profile-box>
<swp-profile-box-label localize="customers.drawer.hairType">Hårtype</swp-profile-box-label>
<swp-profile-box-value>Medium · Bølget</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box>
<swp-profile-box-label localize="customers.drawer.porosity">Porøsitet</swp-profile-box-label>
<swp-profile-box-value>Medium</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box>
<swp-profile-box-label localize="customers.drawer.preference">Præference</swp-profile-box-label>
<swp-profile-box-value>Kold tone, ikke for mørk</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box class="warning">
<swp-profile-box-label localize="customers.drawer.warnings">Advarsler</swp-profile-box-label>
<swp-profile-box-value>Parfume-allergi</swp-profile-box-value>
</swp-profile-box>
</swp-profile-boxes>
</div>
<!-- Chart -->
<swp-chart-section>
<swp-chart-header>
<swp-section-label style="margin-bottom: 0;" localize="customers.drawer.revenueChart">Omsætning (sidste 6 mdr)</swp-section-label>
<swp-chart-legend>
<swp-chart-legend-item>
<swp-chart-legend-dot class="services"></swp-chart-legend-dot>
<span localize="customers.drawer.services">Services</span>
</swp-chart-legend-item>
<swp-chart-legend-item>
<swp-chart-legend-dot class="products"></swp-chart-legend-dot>
<span localize="customers.drawer.products">Produkter</span>
</swp-chart-legend-item>
</swp-chart-legend>
</swp-chart-header>
<swp-chart-container id="customerChart"></swp-chart-container>
</swp-chart-section>
<!-- Notes -->
<swp-notes-section>
<swp-section-label localize="customers.drawer.recentNotes">Seneste noter</swp-section-label>
<swp-note-item>
<swp-note-meta>
<swp-note-type localize="customers.drawer.noteType">Note</swp-note-type>
<swp-note-date>9. dec 2025</swp-note-date>
</swp-note-meta>
<swp-note-text>Kunden foretrækker naturlige farver og ønsker lidt ekstra tid til konsultation.</swp-note-text>
</swp-note-item>
<swp-note-item>
<swp-note-meta>
<swp-note-type localize="customers.drawer.colorFormula">Farveformel</swp-note-type>
<swp-note-date>12. nov 2025</swp-note-date>
</swp-note-meta>
<swp-note-text>7/1 + 7/0 (1:1) · Oxidant 6% · Virketid 35 min</swp-note-text>
</swp-note-item>
<swp-see-all-link localize="customers.drawer.seeAllNotes">Se alle noter →</swp-see-all-link>
</swp-notes-section>
</swp-drawer-body>
</div>
<!-- Create Customer Drawer -->
<div id="create-customer-drawer" data-drawer="lg">
<swp-drawer-header>
<swp-drawer-title>
<i class="ph ph-user-plus"></i>
<span localize="customers.createDrawer.title">Opret ny kunde</span>
</swp-drawer-title>
<swp-drawer-close data-drawer-close>
<i class="ph ph-x"></i>
</swp-drawer-close>
</swp-drawer-header>
<swp-drawer-body>
<!-- Navn (påkrævet) -->
<swp-form-row>
<swp-form-label localize="customers.createDrawer.name">Navn *</swp-form-label>
<input type="text" id="createCustomerName" required>
</swp-form-row>
<!-- Kontaktoplysninger Card -->
<swp-card>
<swp-card-header>
<swp-card-title>
<i class="ph ph-address-book"></i>
<span localize="customers.drawer.contactInfo">Kontaktoplysninger</span>
</swp-card-title>
</swp-card-header>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label localize="customers.drawer.phone">Telefon</swp-edit-label>
<swp-edit-input>
<input type="tel" id="createCustomerPhone">
</swp-edit-input>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label localize="customers.drawer.email">Email</swp-edit-label>
<swp-edit-input>
<input type="email" id="createCustomerEmail">
</swp-edit-input>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label localize="customers.drawer.address">Adresse</swp-edit-label>
<swp-edit-input>
<input type="text" id="createCustomerAddress">
</swp-edit-input>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label localize="customers.drawer.zipCity">Postnr + By</swp-edit-label>
<swp-edit-input>
<input type="text" id="createCustomerZip" class="short">
<input type="text" id="createCustomerCity">
</swp-edit-input>
</swp-edit-row>
</swp-edit-section>
</swp-card>
<!-- Note -->
<swp-form-row class="note-field">
<swp-form-label localize="customers.createDrawer.note">Note</swp-form-label>
<textarea id="createCustomerNote" rows="3" localize-placeholder="customers.createDrawer.notePlaceholder" placeholder="Skriv en note om kunden..."></textarea>
</swp-form-row>
</swp-drawer-body>
<swp-drawer-footer>
<swp-btn class="secondary" data-drawer-close>
<span localize="common.cancel">Annuller</span>
</swp-btn>
<swp-btn class="primary" id="saveNewCustomer">
<span localize="customers.createDrawer.save">Opret kunde</span>
</swp-btn>
</swp-drawer-footer>
</div>
@section Scripts {
<script>
// Row click - navigate to detail page
document.querySelectorAll('swp-data-table-row[data-href]').forEach(row => {
row.addEventListener('click', (e) => {
// Don't navigate if clicking the quick-view button
if (e.target.closest('swp-quick-view-btn')) {
return;
}
const href = row.dataset.href;
if (href) {
window.location.href = href;
}
});
});
// Quick-view button click - update drawer data before it opens
// Note: The drawer opening is handled by the global drawer system via data-drawer-trigger
document.querySelectorAll('swp-quick-view-btn[data-drawer-trigger="customer-drawer"]').forEach(btn => {
btn.addEventListener('click', (e) => {
// Don't stop propagation - let the event bubble up to the drawer system
const row = btn.closest('swp-data-table-row');
const drawer = document.getElementById('customer-drawer');
const detailLink = document.getElementById('openFullDetailLink');
// Get customer data from row
const customerName = row.dataset.name || 'unknown';
const customerId = customerName.toLowerCase().replace(/\s+/g, '-');
// Update drawer data attribute and link href
drawer.dataset.customerId = customerId;
detailLink.href = `/kunder/${customerId}`;
});
});
</script>
}