2026-01-19 14:43:48 +01:00
@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>
2026-01-21 18:00:53 +01:00
@await Component.InvokeAsync("CustomerTable")
2026-01-19 14:43:48 +01:00
</swp-page-container>
2026-01-19 18:27:59 +01:00
<!-- Customer Drawer -->
2026-01-19 23:27:18 +01:00
<div id="customer-drawer" data-drawer="xxl" data-customer-id="">
2026-01-19 18:27:59 +01:00
<swp-drawer-header>
<swp-drawer-title>
<i class="ph ph-user"></i>
<span localize="customers.drawer.title">Kundekort</span>
</swp-drawer-title>
2026-01-19 23:27:18 +01:00
<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>
2026-01-19 18:27:59 +01:00
</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>
2026-01-19 23:27:18 +01:00
2026-01-24 10:59:21 +01:00
<!-- 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>
2026-01-19 23:27:18 +01:00
@section Scripts {
<script>
2026-01-20 21:32:03 +01:00
// 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');
2026-01-19 23:27:18 +01:00
const drawer = document.getElementById('customer-drawer');
const detailLink = document.getElementById('openFullDetailLink');
2026-01-20 21:32:03 +01:00
// Get customer data from row
2026-01-19 23:27:18 +01:00
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>
}