Enhance POC dashboard with dynamic UI components
Adds comprehensive dashboard HTML with responsive design and interactive elements Implements: - Dark/light mode color variables - Responsive grid layout - Interactive booking and notification sections - Dynamic time and status tracking - Custom web components for dashboard functionality
This commit is contained in:
parent
196129b74a
commit
0fa5b60a6b
2 changed files with 1714 additions and 17 deletions
1385
wwwroot/poc-dashboard.html
Normal file
1385
wwwroot/poc-dashboard.html
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -898,6 +898,172 @@
|
|||
min-height: 100px;
|
||||
}
|
||||
|
||||
/* ==========================================
|
||||
ADD VALUE DRAWER
|
||||
========================================== */
|
||||
swp-balance-info-box {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
background: var(--color-background-alt);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
swp-balance-info-box swp-current-amount {
|
||||
display: block;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
font-family: var(--font-mono);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
swp-balance-info-box swp-original-amount {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
color: var(--color-text-secondary);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
swp-new-balance-box {
|
||||
display: block;
|
||||
padding: 16px;
|
||||
background: color-mix(in srgb, var(--color-green) 10%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--color-green) 30%, transparent);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
swp-new-balance-box swp-new-amount {
|
||||
display: block;
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
font-family: var(--font-mono);
|
||||
color: var(--color-green);
|
||||
}
|
||||
|
||||
swp-new-balance-box swp-new-label {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
color: var(--color-text-secondary);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
swp-quick-amounts {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
swp-quick-amount {
|
||||
padding: 8px 16px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
font-family: var(--font-mono);
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text);
|
||||
cursor: pointer;
|
||||
transition: all 150ms ease;
|
||||
}
|
||||
|
||||
swp-quick-amount:hover {
|
||||
background: var(--color-background-hover);
|
||||
border-color: var(--color-teal);
|
||||
}
|
||||
|
||||
swp-quick-amount.selected {
|
||||
background: color-mix(in srgb, var(--color-teal) 10%, transparent);
|
||||
border-color: var(--color-teal);
|
||||
color: var(--color-teal);
|
||||
}
|
||||
|
||||
/* Toggle Slider (Ja/Nej) */
|
||||
swp-toggle-slider {
|
||||
display: inline-flex;
|
||||
width: fit-content;
|
||||
background: var(--color-background);
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--color-border);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
swp-toggle-slider::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: calc(50% - 4px);
|
||||
height: calc(100% - 4px);
|
||||
background: color-mix(in srgb, var(--color-green) 18%, white);
|
||||
border-radius: 4px;
|
||||
transition: transform 200ms ease, background 200ms ease;
|
||||
}
|
||||
|
||||
swp-toggle-slider[data-value="no"]::before {
|
||||
transform: translateX(100%);
|
||||
background: color-mix(in srgb, var(--color-red) 18%, white);
|
||||
}
|
||||
|
||||
swp-toggle-option {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 5px 16px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
transition: color 150ms ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
swp-toggle-slider[data-value="yes"] swp-toggle-option:first-child {
|
||||
color: var(--color-green);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
swp-toggle-slider[data-value="no"] swp-toggle-option:last-child {
|
||||
color: var(--color-red);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
swp-date-extend {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
swp-current-expiry {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 13px;
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
swp-current-expiry i {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
swp-current-expiry strong {
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
swp-date-extend input[type="date"] {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
font-family: var(--font-family);
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text);
|
||||
transition: border-color 150ms ease;
|
||||
}
|
||||
|
||||
swp-date-extend input[type="date"]:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-teal);
|
||||
}
|
||||
|
||||
/* ==========================================
|
||||
RESPONSIVE
|
||||
========================================== */
|
||||
|
|
@ -948,20 +1114,12 @@
|
|||
<swp-expiry-label>Udløbsdato</swp-expiry-label>
|
||||
<swp-expiry-date>31. december 2025</swp-expiry-date>
|
||||
</swp-expiry-info>
|
||||
<swp-btn class="secondary" style="padding: 8px 12px; font-size: 12px;">
|
||||
<i class="ph ph-calendar-plus"></i>
|
||||
Forlæng
|
||||
</swp-btn>
|
||||
<swp-btn class="danger" style="padding: 8px 12px; font-size: 12px;">
|
||||
<i class="ph ph-x-circle"></i>
|
||||
Deaktiver
|
||||
</swp-btn>
|
||||
</swp-expiry-box>
|
||||
|
||||
<swp-actions-row>
|
||||
<swp-btn class="secondary">
|
||||
<i class="ph ph-plus-circle"></i>
|
||||
Tilføj værdi
|
||||
<swp-btn class="secondary" id="openAddValueDrawer">
|
||||
<i class="ph ph-sliders-horizontal"></i>
|
||||
Juster
|
||||
</swp-btn>
|
||||
<swp-btn class="secondary" id="openEmailDrawer">
|
||||
<i class="ph ph-envelope"></i>
|
||||
|
|
@ -997,6 +1155,15 @@
|
|||
<swp-kv-label>Original værdi</swp-kv-label>
|
||||
<swp-kv-value class="mono">500 DKK</swp-kv-value>
|
||||
</swp-kv-row>
|
||||
<swp-kv-row>
|
||||
<swp-kv-label>Aktiv</swp-kv-label>
|
||||
<swp-kv-value>
|
||||
<swp-toggle-slider data-value="yes" id="activeToggle">
|
||||
<swp-toggle-option>Ja</swp-toggle-option>
|
||||
<swp-toggle-option>Nej</swp-toggle-option>
|
||||
</swp-toggle-slider>
|
||||
</swp-kv-value>
|
||||
</swp-kv-row>
|
||||
</swp-kv-list>
|
||||
</swp-card>
|
||||
|
||||
|
|
@ -1141,6 +1308,69 @@
|
|||
</swp-drawer-footer>
|
||||
</swp-drawer>
|
||||
|
||||
<!-- Add Value Drawer -->
|
||||
<swp-drawer id="addValueDrawer">
|
||||
<swp-drawer-header>
|
||||
<swp-drawer-title>Juster gavekort</swp-drawer-title>
|
||||
<swp-drawer-close id="closeAddValueDrawer">
|
||||
<i class="ph ph-x"></i>
|
||||
</swp-drawer-close>
|
||||
</swp-drawer-header>
|
||||
|
||||
<swp-drawer-content>
|
||||
<swp-form-field>
|
||||
<swp-form-label>Nuværende saldo</swp-form-label>
|
||||
<swp-balance-info-box>
|
||||
<swp-current-amount>350 DKK</swp-current-amount>
|
||||
<swp-original-amount>af 500 DKK original værdi</swp-original-amount>
|
||||
</swp-balance-info-box>
|
||||
</swp-form-field>
|
||||
|
||||
<swp-form-field>
|
||||
<swp-form-label>Beløb at tilføje</swp-form-label>
|
||||
<input type="text" id="addValueAmount" class="mono" placeholder="Indtast beløb" value="100 DKK" />
|
||||
<swp-quick-amounts>
|
||||
<swp-quick-amount data-value="50">50 DKK</swp-quick-amount>
|
||||
<swp-quick-amount data-value="100" class="selected">100 DKK</swp-quick-amount>
|
||||
<swp-quick-amount data-value="200">200 DKK</swp-quick-amount>
|
||||
<swp-quick-amount data-value="500">500 DKK</swp-quick-amount>
|
||||
</swp-quick-amounts>
|
||||
</swp-form-field>
|
||||
|
||||
<swp-form-field>
|
||||
<swp-form-label>Ny saldo</swp-form-label>
|
||||
<swp-new-balance-box>
|
||||
<swp-new-amount id="newBalanceAmount">450 DKK</swp-new-amount>
|
||||
<swp-new-label>Efter tilføjelse</swp-new-label>
|
||||
</swp-new-balance-box>
|
||||
</swp-form-field>
|
||||
|
||||
<swp-form-field>
|
||||
<swp-form-label>Forlæng udløbsdato (valgfri)</swp-form-label>
|
||||
<swp-date-extend>
|
||||
<swp-current-expiry>
|
||||
<i class="ph ph-calendar"></i>
|
||||
<span>Nuværende: <strong>31. december 2025</strong></span>
|
||||
</swp-current-expiry>
|
||||
<input type="date" id="newExpiryDate" value="2026-12-31" />
|
||||
</swp-date-extend>
|
||||
</swp-form-field>
|
||||
|
||||
<swp-form-field>
|
||||
<swp-form-label>Intern note</swp-form-label>
|
||||
<textarea id="addValueNote" placeholder="Beskriv hvorfor værdi tilføjes..."></textarea>
|
||||
</swp-form-field>
|
||||
</swp-drawer-content>
|
||||
|
||||
<swp-drawer-footer>
|
||||
<swp-btn class="secondary" id="cancelAddValue">Annuller</swp-btn>
|
||||
<swp-btn class="primary" id="confirmAddValue">
|
||||
<i class="ph ph-check"></i>
|
||||
Gem ændringer
|
||||
</swp-btn>
|
||||
</swp-drawer-footer>
|
||||
</swp-drawer>
|
||||
|
||||
<script>
|
||||
// Elements
|
||||
const overlay = document.getElementById('overlay');
|
||||
|
|
@ -1197,7 +1427,6 @@
|
|||
openEmailBtnAlt.addEventListener('click', openEmailDrawerFn);
|
||||
closeEmailBtn.addEventListener('click', closeEmailDrawerFn);
|
||||
cancelEmailBtn.addEventListener('click', closeEmailDrawerFn);
|
||||
overlay.addEventListener('click', closeEmailDrawerFn);
|
||||
|
||||
// Real-time preview updates
|
||||
personalMessageInput.addEventListener('input', updatePreview);
|
||||
|
|
@ -1209,13 +1438,96 @@
|
|||
closeEmailDrawerFn();
|
||||
});
|
||||
|
||||
// Close on Escape
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') closeEmailDrawerFn();
|
||||
});
|
||||
|
||||
// Initialize preview
|
||||
updatePreview();
|
||||
|
||||
// ==========================================
|
||||
// ADD VALUE DRAWER
|
||||
// ==========================================
|
||||
const addValueDrawer = document.getElementById('addValueDrawer');
|
||||
const openAddValueBtn = document.getElementById('openAddValueDrawer');
|
||||
const closeAddValueBtn = document.getElementById('closeAddValueDrawer');
|
||||
const cancelAddValueBtn = document.getElementById('cancelAddValue');
|
||||
const confirmAddValueBtn = document.getElementById('confirmAddValue');
|
||||
const addValueAmountInput = document.getElementById('addValueAmount');
|
||||
const newBalanceAmount = document.getElementById('newBalanceAmount');
|
||||
const addValueQuickAmounts = document.querySelectorAll('#addValueDrawer swp-quick-amount');
|
||||
|
||||
const currentBalance = 350; // Demo value
|
||||
|
||||
// Open add value drawer
|
||||
function openAddValueDrawerFn() {
|
||||
overlay.classList.add('open');
|
||||
addValueDrawer.classList.add('open');
|
||||
document.body.style.overflow = 'hidden';
|
||||
updateNewBalance();
|
||||
}
|
||||
|
||||
// Close add value drawer
|
||||
function closeAddValueDrawerFn() {
|
||||
overlay.classList.remove('open');
|
||||
addValueDrawer.classList.remove('open');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
|
||||
// Parse amount from string
|
||||
function parseAmount(str) {
|
||||
const num = parseInt(str.replace(/[^\d]/g, ''), 10);
|
||||
return isNaN(num) ? 0 : num;
|
||||
}
|
||||
|
||||
// Update new balance calculation
|
||||
function updateNewBalance() {
|
||||
const addAmount = parseAmount(addValueAmountInput.value);
|
||||
const newBalance = currentBalance + addAmount;
|
||||
newBalanceAmount.textContent = newBalance.toLocaleString('da-DK') + ' DKK';
|
||||
}
|
||||
|
||||
// Event listeners
|
||||
openAddValueBtn.addEventListener('click', openAddValueDrawerFn);
|
||||
closeAddValueBtn.addEventListener('click', closeAddValueDrawerFn);
|
||||
cancelAddValueBtn.addEventListener('click', closeAddValueDrawerFn);
|
||||
|
||||
// Quick amount selection
|
||||
addValueQuickAmounts.forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
addValueQuickAmounts.forEach(b => b.classList.remove('selected'));
|
||||
btn.classList.add('selected');
|
||||
const value = btn.dataset.value;
|
||||
addValueAmountInput.value = Number(value).toLocaleString('da-DK') + ' DKK';
|
||||
updateNewBalance();
|
||||
});
|
||||
});
|
||||
|
||||
// Live update on input
|
||||
addValueAmountInput.addEventListener('input', updateNewBalance);
|
||||
|
||||
// Confirm add value (demo)
|
||||
confirmAddValueBtn.addEventListener('click', () => {
|
||||
alert('Værdi tilføjet! (Demo)');
|
||||
closeAddValueDrawerFn();
|
||||
});
|
||||
|
||||
// Update overlay click to close any open drawer
|
||||
overlay.addEventListener('click', () => {
|
||||
closeEmailDrawerFn();
|
||||
closeAddValueDrawerFn();
|
||||
});
|
||||
|
||||
// Update Escape to close any drawer
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
closeEmailDrawerFn();
|
||||
closeAddValueDrawerFn();
|
||||
}
|
||||
});
|
||||
|
||||
// Toggle sliders (Ja/Nej)
|
||||
document.querySelectorAll('swp-toggle-slider').forEach(slider => {
|
||||
slider.addEventListener('click', () => {
|
||||
slider.dataset.value = slider.dataset.value === 'yes' ? 'no' : 'yes';
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue