Creates a detailed HTML prototype for cash reconciliation process Includes comprehensive UI components for tracking daily cash operations Implements interactive calculations and user input validation for cash counting
976 lines
26 KiB
HTML
976 lines
26 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="da">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Kasseafstemning - POC</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
/* ==========================================
|
||
FONT FACE (Poppins)
|
||
========================================== */
|
||
@font-face {
|
||
font-family: 'Poppins';
|
||
src: url('fonts/Poppins-Regular.woff') format('woff');
|
||
font-weight: 400;
|
||
font-style: normal;
|
||
font-display: swap;
|
||
}
|
||
@font-face {
|
||
font-family: 'Poppins';
|
||
src: url('fonts/Poppins-Medium.woff') format('woff');
|
||
font-weight: 500;
|
||
font-style: normal;
|
||
font-display: swap;
|
||
}
|
||
@font-face {
|
||
font-family: 'Poppins';
|
||
src: url('fonts/Poppins-SemiBold.woff') format('woff');
|
||
font-weight: 600;
|
||
font-style: normal;
|
||
font-display: swap;
|
||
}
|
||
@font-face {
|
||
font-family: 'Poppins';
|
||
src: url('fonts/Poppins-Bold.woff') format('woff');
|
||
font-weight: 700;
|
||
font-style: normal;
|
||
font-display: swap;
|
||
}
|
||
|
||
/* ==========================================
|
||
CSS VARIABLES (Design System)
|
||
========================================== */
|
||
:root {
|
||
--color-surface: #fff;
|
||
--color-background: #f5f5f5;
|
||
--color-background-hover: #f0f0f0;
|
||
--color-background-alt: #fafafa;
|
||
--color-border: #e0e0e0;
|
||
--color-text: #333;
|
||
--color-text-secondary: #666;
|
||
--color-teal: #00897b;
|
||
--color-blue: #1976d2;
|
||
--color-red: #e53935;
|
||
--color-amber: #f59e0b;
|
||
--color-purple: #8b5cf6;
|
||
--color-green: #43a047;
|
||
--font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
--font-mono: 'JetBrains Mono', monospace;
|
||
}
|
||
|
||
/* ==========================================
|
||
RESET & BASE
|
||
========================================== */
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: var(--font-family);
|
||
font-size: 14px;
|
||
color: var(--color-text);
|
||
background: var(--color-background);
|
||
line-height: 1.5;
|
||
}
|
||
|
||
/* ==========================================
|
||
TOPBAR
|
||
========================================== */
|
||
swp-topbar {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 12px 24px;
|
||
background: var(--color-surface);
|
||
border-bottom: 1px solid var(--color-border);
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 100;
|
||
}
|
||
|
||
swp-topbar-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16px;
|
||
}
|
||
|
||
swp-back-link {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
color: var(--color-text-secondary);
|
||
text-decoration: none;
|
||
font-size: 13px;
|
||
cursor: pointer;
|
||
transition: color 150ms ease;
|
||
}
|
||
|
||
swp-back-link:hover {
|
||
color: var(--color-teal);
|
||
}
|
||
|
||
swp-page-title {
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
swp-topbar-right {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
}
|
||
|
||
/* ==========================================
|
||
LAYOUT
|
||
========================================== */
|
||
swp-page-container {
|
||
display: block;
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
padding: 24px;
|
||
}
|
||
|
||
.grid-2 {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 24px;
|
||
}
|
||
|
||
@media (max-width: 900px) {
|
||
.grid-2 { grid-template-columns: 1fr; }
|
||
}
|
||
|
||
/* ==========================================
|
||
PAGE HEADER
|
||
========================================== */
|
||
swp-page-header {
|
||
display: block;
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
swp-page-header h1 {
|
||
font-size: 24px;
|
||
font-weight: 600;
|
||
color: var(--color-text);
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
swp-page-subtitle {
|
||
display: block;
|
||
font-size: 14px;
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
/* ==========================================
|
||
CARDS
|
||
========================================== */
|
||
swp-card {
|
||
display: block;
|
||
background: var(--color-surface);
|
||
border-radius: 8px;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||
margin-bottom: 20px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
swp-card-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 16px 20px;
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
swp-card-title {
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
color: var(--color-text);
|
||
}
|
||
|
||
swp-card-hint {
|
||
font-size: 12px;
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
swp-card-body {
|
||
display: block;
|
||
padding: 20px;
|
||
}
|
||
|
||
/* ==========================================
|
||
FORM ELEMENTS
|
||
========================================== */
|
||
swp-form-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 16px;
|
||
}
|
||
|
||
swp-form-field {
|
||
display: block;
|
||
}
|
||
|
||
swp-form-field.full-width {
|
||
grid-column: 1 / -1;
|
||
}
|
||
|
||
swp-form-label {
|
||
display: block;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
color: var(--color-text-secondary);
|
||
margin-bottom: 6px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.3px;
|
||
}
|
||
|
||
swp-form-label .required {
|
||
color: var(--color-red);
|
||
}
|
||
|
||
swp-form-input input,
|
||
swp-form-input select {
|
||
width: 100%;
|
||
padding: 10px 12px;
|
||
font-size: 14px;
|
||
font-family: var(--font-family);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: 6px;
|
||
background: var(--color-surface);
|
||
transition: border-color 150ms ease;
|
||
}
|
||
|
||
swp-form-input input:focus,
|
||
swp-form-input select:focus {
|
||
outline: none;
|
||
border-color: var(--color-teal);
|
||
}
|
||
|
||
swp-auto-id {
|
||
display: block;
|
||
font-size: 12px;
|
||
color: var(--color-text-secondary);
|
||
margin-top: 16px;
|
||
padding-top: 16px;
|
||
border-top: 1px solid var(--color-border);
|
||
}
|
||
|
||
/* ==========================================
|
||
DATA TABLE
|
||
========================================== */
|
||
swp-data-table {
|
||
display: block;
|
||
width: 100%;
|
||
}
|
||
|
||
swp-data-header {
|
||
display: grid;
|
||
grid-template-columns: 1fr 100px 140px;
|
||
gap: 12px;
|
||
padding: 10px 0;
|
||
border-bottom: 2px solid var(--color-border);
|
||
}
|
||
|
||
swp-data-header span {
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
swp-data-header span:not(:first-child) {
|
||
text-align: right;
|
||
}
|
||
|
||
swp-data-row {
|
||
display: grid;
|
||
grid-template-columns: 1fr 100px 140px;
|
||
gap: 12px;
|
||
padding: 14px 0;
|
||
border-bottom: 1px solid var(--color-border);
|
||
align-items: center;
|
||
}
|
||
|
||
swp-data-row:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
swp-data-label {
|
||
font-size: 14px;
|
||
color: var(--color-text);
|
||
}
|
||
|
||
swp-data-system {
|
||
text-align: right;
|
||
font-family: var(--font-mono);
|
||
font-size: 14px;
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
swp-data-input input {
|
||
width: 100%;
|
||
padding: 8px 10px;
|
||
font-size: 14px;
|
||
font-family: var(--font-mono);
|
||
text-align: right;
|
||
border: 1px solid var(--color-border);
|
||
border-radius: 6px;
|
||
background: var(--color-surface);
|
||
}
|
||
|
||
swp-data-input input:focus {
|
||
outline: none;
|
||
border-color: var(--color-teal);
|
||
}
|
||
|
||
swp-data-input input::placeholder {
|
||
color: #bbb;
|
||
font-family: var(--font-family);
|
||
font-size: 12px;
|
||
}
|
||
|
||
swp-data-value {
|
||
text-align: right;
|
||
font-family: var(--font-mono);
|
||
font-size: 14px;
|
||
color: var(--color-text);
|
||
}
|
||
|
||
swp-data-value.muted {
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
swp-table-note {
|
||
display: block;
|
||
font-size: 12px;
|
||
color: var(--color-text-secondary);
|
||
margin-top: 16px;
|
||
padding: 12px;
|
||
background: var(--color-background-alt);
|
||
border-radius: 6px;
|
||
}
|
||
|
||
/* ==========================================
|
||
CASH CALCULATION
|
||
========================================== */
|
||
swp-calc-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 14px 0;
|
||
border-bottom: 1px solid var(--color-border);
|
||
}
|
||
|
||
swp-calc-row:last-of-type {
|
||
border-bottom: none;
|
||
}
|
||
|
||
swp-calc-row.input-row {
|
||
padding: 18px 0;
|
||
background: var(--color-background-alt);
|
||
margin: 16px -20px -20px -20px;
|
||
padding: 20px;
|
||
border-radius: 0 0 8px 8px;
|
||
}
|
||
|
||
swp-calc-label span {
|
||
display: block;
|
||
font-size: 14px;
|
||
color: var(--color-text);
|
||
}
|
||
|
||
swp-calc-label small {
|
||
display: block;
|
||
font-size: 12px;
|
||
color: var(--color-text-secondary);
|
||
margin-top: 2px;
|
||
}
|
||
|
||
swp-calc-value {
|
||
font-family: var(--font-mono);
|
||
font-size: 14px;
|
||
color: var(--color-text);
|
||
}
|
||
|
||
swp-calc-value.muted {
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
swp-calc-input input {
|
||
width: 140px;
|
||
padding: 12px 14px;
|
||
font-size: 16px;
|
||
font-family: var(--font-mono);
|
||
text-align: right;
|
||
border: 2px solid var(--color-border);
|
||
border-radius: 6px;
|
||
background: var(--color-surface);
|
||
}
|
||
|
||
swp-calc-input input:focus {
|
||
outline: none;
|
||
border-color: var(--color-teal);
|
||
}
|
||
|
||
/* ==========================================
|
||
DIFFERENCE BOX
|
||
========================================== */
|
||
swp-difference-box {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
background: var(--color-background-alt);
|
||
margin-top: 16px;
|
||
}
|
||
|
||
swp-difference-box.positive {
|
||
background: color-mix(in srgb, var(--color-green) 10%, white);
|
||
}
|
||
|
||
swp-difference-box.negative {
|
||
background: color-mix(in srgb, var(--color-red) 10%, white);
|
||
}
|
||
|
||
swp-difference-box.neutral {
|
||
background: color-mix(in srgb, var(--color-teal) 10%, white);
|
||
}
|
||
|
||
swp-difference-label {
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
color: var(--color-text);
|
||
}
|
||
|
||
swp-difference-label small {
|
||
display: block;
|
||
font-size: 12px;
|
||
font-weight: 400;
|
||
color: var(--color-text-secondary);
|
||
margin-top: 4px;
|
||
}
|
||
|
||
swp-difference-value {
|
||
font-size: 24px;
|
||
font-weight: 600;
|
||
font-family: var(--font-mono);
|
||
}
|
||
|
||
swp-difference-box.positive swp-difference-value {
|
||
color: var(--color-green);
|
||
}
|
||
|
||
swp-difference-box.negative swp-difference-value {
|
||
color: var(--color-red);
|
||
}
|
||
|
||
swp-difference-box.neutral swp-difference-value {
|
||
color: var(--color-teal);
|
||
}
|
||
|
||
/* ==========================================
|
||
NOTE FIELD
|
||
========================================== */
|
||
swp-note-field textarea {
|
||
width: 100%;
|
||
min-height: 80px;
|
||
padding: 12px;
|
||
font-size: 14px;
|
||
font-family: var(--font-family);
|
||
border: 1px solid var(--color-border);
|
||
border-radius: 6px;
|
||
resize: vertical;
|
||
}
|
||
|
||
swp-note-field textarea:focus {
|
||
outline: none;
|
||
border-color: var(--color-teal);
|
||
}
|
||
|
||
swp-note-hint {
|
||
display: block;
|
||
font-size: 12px;
|
||
color: var(--color-text-secondary);
|
||
margin-top: 8px;
|
||
}
|
||
|
||
/* ==========================================
|
||
STATUS & APPROVAL
|
||
========================================== */
|
||
swp-status-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
swp-status-label {
|
||
font-size: 13px;
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
swp-status-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 6px 12px;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
border-radius: 20px;
|
||
}
|
||
|
||
swp-status-badge.draft {
|
||
background: color-mix(in srgb, var(--color-amber) 15%, white);
|
||
color: #b45309;
|
||
}
|
||
|
||
swp-status-badge.approved {
|
||
background: color-mix(in srgb, var(--color-green) 15%, white);
|
||
color: var(--color-green);
|
||
}
|
||
|
||
swp-status-badge::before {
|
||
content: '';
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
background: currentColor;
|
||
}
|
||
|
||
swp-approval-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 16px;
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
swp-checkbox-field {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 12px;
|
||
padding: 16px;
|
||
background: var(--color-background-alt);
|
||
border-radius: 8px;
|
||
margin-bottom: 20px;
|
||
grid-column: 1 / -1;
|
||
}
|
||
|
||
swp-checkbox-field input[type="checkbox"] {
|
||
width: 18px;
|
||
height: 18px;
|
||
margin-top: 2px;
|
||
accent-color: var(--color-teal);
|
||
cursor: pointer;
|
||
}
|
||
|
||
swp-checkbox-field label {
|
||
font-size: 13px;
|
||
color: var(--color-text);
|
||
cursor: pointer;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
/* ==========================================
|
||
ACTIONS
|
||
========================================== */
|
||
swp-card-footer {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 16px 20px;
|
||
background: var(--color-background-alt);
|
||
border-top: 1px solid var(--color-border);
|
||
}
|
||
|
||
swp-actions-right {
|
||
display: flex;
|
||
gap: 10px;
|
||
}
|
||
|
||
swp-btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
padding: 10px 18px;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
font-family: var(--font-family);
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
transition: all 150ms ease;
|
||
}
|
||
|
||
swp-btn.ghost {
|
||
background: transparent;
|
||
border: none;
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
swp-btn.ghost:hover {
|
||
color: var(--color-text);
|
||
}
|
||
|
||
swp-btn.secondary {
|
||
background: var(--color-surface);
|
||
border: 1px solid var(--color-border);
|
||
color: var(--color-text);
|
||
}
|
||
|
||
swp-btn.secondary:hover {
|
||
background: var(--color-background-hover);
|
||
}
|
||
|
||
swp-btn.primary {
|
||
background: var(--color-teal);
|
||
border: 1px solid var(--color-teal);
|
||
color: white;
|
||
}
|
||
|
||
swp-btn.primary:hover {
|
||
background: #00796b;
|
||
}
|
||
|
||
swp-btn.primary:disabled {
|
||
background: #ccc;
|
||
border-color: #ccc;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
swp-system-note {
|
||
display: block;
|
||
font-size: 11px;
|
||
color: var(--color-text-secondary);
|
||
text-align: center;
|
||
padding: 12px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<!-- Topbar -->
|
||
<swp-topbar>
|
||
<swp-topbar-left>
|
||
<swp-back-link>
|
||
<svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
|
||
Tilbage
|
||
</swp-back-link>
|
||
<swp-page-title>Kasseafstemning</swp-page-title>
|
||
</swp-topbar-left>
|
||
<swp-topbar-right>
|
||
<swp-status-badge class="draft" id="statusBadge">Kladde</swp-status-badge>
|
||
</swp-topbar-right>
|
||
</swp-topbar>
|
||
|
||
<swp-page-container>
|
||
<!-- Page Header -->
|
||
<swp-page-header>
|
||
<h1>Kasseafstemning</h1>
|
||
<swp-page-subtitle>Enkel dagsafslutning med fokus på kontanter. Kort afstemmes separat mod bank/indløser.</swp-page-subtitle>
|
||
</swp-page-header>
|
||
|
||
<div class="grid-2">
|
||
<!-- VENSTRE KOLONNE -->
|
||
<div>
|
||
<!-- Dagens tal -->
|
||
<swp-card>
|
||
<swp-card-header>
|
||
<swp-card-title>Dagens tal</swp-card-title>
|
||
<swp-card-hint>Systemtal vs. kontrol</swp-card-hint>
|
||
</swp-card-header>
|
||
<swp-card-body>
|
||
<swp-data-table>
|
||
<swp-data-header>
|
||
<span>Type</span>
|
||
<span>System</span>
|
||
<span>Kontrol</span>
|
||
</swp-data-header>
|
||
|
||
<swp-data-row>
|
||
<swp-data-label>Kortbetalinger</swp-data-label>
|
||
<swp-data-system>12.875,50</swp-data-system>
|
||
<swp-data-input>
|
||
<input type="text" placeholder="Valgfrit" />
|
||
</swp-data-input>
|
||
</swp-data-row>
|
||
|
||
<swp-data-row>
|
||
<swp-data-label>MobilePay / Online</swp-data-label>
|
||
<swp-data-system>2.450,00</swp-data-system>
|
||
<swp-data-input>
|
||
<input type="text" placeholder="Valgfrit" />
|
||
</swp-data-input>
|
||
</swp-data-row>
|
||
|
||
<swp-data-row>
|
||
<swp-data-label>Kontantsalg</swp-data-label>
|
||
<swp-data-system>3.540,00</swp-data-system>
|
||
<swp-data-value class="muted">..</swp-data-value>
|
||
</swp-data-row>
|
||
</swp-data-table>
|
||
|
||
<swp-table-note>Kort og MobilePay afstemmes mod bank/indløser. Kontanter tælles op nedenfor.</swp-table-note>
|
||
</swp-card-body>
|
||
</swp-card>
|
||
|
||
<!-- Kontanter i kassen -->
|
||
<swp-card>
|
||
<swp-card-header>
|
||
<swp-card-title>Kontanter i kassen</swp-card-title>
|
||
</swp-card-header>
|
||
<swp-card-body>
|
||
<swp-calc-row>
|
||
<swp-calc-label>
|
||
<span>Startbeholdning</span>
|
||
<small>Overført fra sidste afstemning</small>
|
||
</swp-calc-label>
|
||
<swp-calc-value class="muted">2.000,00</swp-calc-value>
|
||
</swp-calc-row>
|
||
|
||
<swp-calc-row>
|
||
<swp-calc-label>
|
||
<span>Udbetalinger / Bilag</span>
|
||
<small>Sammentæl bilag betalt kontant</small>
|
||
</swp-calc-label>
|
||
<swp-calc-input>
|
||
<input type="text" id="payouts" placeholder="0,00" />
|
||
</swp-calc-input>
|
||
</swp-calc-row>
|
||
|
||
<swp-calc-row>
|
||
<swp-calc-label>
|
||
<span>Udtaget til bank</span>
|
||
<small>Kontanter lagt til side</small>
|
||
</swp-calc-label>
|
||
<swp-calc-input>
|
||
<input type="text" id="toBank" placeholder="0,00" />
|
||
</swp-calc-input>
|
||
</swp-calc-row>
|
||
|
||
<swp-calc-row>
|
||
<swp-calc-label>
|
||
<span>Forventet kontantbeholdning</span>
|
||
</swp-calc-label>
|
||
<swp-calc-value id="expectedCash">5.220,00</swp-calc-value>
|
||
</swp-calc-row>
|
||
|
||
<swp-calc-row class="input-row">
|
||
<swp-calc-label>
|
||
<span>Optalt kontantbeholdning <span style="color: var(--color-red)">*</span></span>
|
||
<small>Hvad ligger der faktisk i kassen?</small>
|
||
</swp-calc-label>
|
||
<swp-calc-input>
|
||
<input type="text" id="actualCash" placeholder="0,00" />
|
||
</swp-calc-input>
|
||
</swp-calc-row>
|
||
</swp-card-body>
|
||
</swp-card>
|
||
|
||
<!-- Difference -->
|
||
<swp-difference-box id="differenceBox" class="neutral">
|
||
<swp-difference-label>
|
||
Kontant difference
|
||
<small>Optalt minus forventet</small>
|
||
</swp-difference-label>
|
||
<swp-difference-value id="differenceValue">– kr</swp-difference-value>
|
||
</swp-difference-box>
|
||
</div>
|
||
|
||
<!-- HØJRE KOLONNE -->
|
||
<div>
|
||
<!-- Dagsoplysninger -->
|
||
<swp-card>
|
||
<swp-card-header>
|
||
<swp-card-title>Dagsoplysninger</swp-card-title>
|
||
<swp-card-hint>Identificér afstemningen</swp-card-hint>
|
||
</swp-card-header>
|
||
<swp-card-body>
|
||
<swp-form-grid>
|
||
<swp-form-field>
|
||
<swp-form-label>Dato <span class="required">*</span></swp-form-label>
|
||
<swp-form-input>
|
||
<input type="date" id="reconciliationDate" />
|
||
</swp-form-input>
|
||
</swp-form-field>
|
||
|
||
<swp-form-field>
|
||
<swp-form-label>Medarbejder <span class="required">*</span></swp-form-label>
|
||
<swp-form-input>
|
||
<select id="employee">
|
||
<option>Anna Jensen</option>
|
||
<option>Karina Knudsen</option>
|
||
<option>Martin Nielsen</option>
|
||
</select>
|
||
</swp-form-input>
|
||
</swp-form-field>
|
||
|
||
<swp-form-field>
|
||
<swp-form-label>Kassepunkt <span class="required">*</span></swp-form-label>
|
||
<swp-form-input>
|
||
<select id="register">
|
||
<option>Kasse 1 – Reception</option>
|
||
<option>Kasse 2 – Salon</option>
|
||
</select>
|
||
</swp-form-input>
|
||
</swp-form-field>
|
||
|
||
<swp-form-field>
|
||
<swp-form-label>Skift (valgfrit)</swp-form-label>
|
||
<swp-form-input>
|
||
<select id="shift">
|
||
<option>Ikke angivet</option>
|
||
<option>Morgen (08-14)</option>
|
||
<option>Eftermiddag (14-20)</option>
|
||
</select>
|
||
</swp-form-input>
|
||
</swp-form-field>
|
||
</swp-form-grid>
|
||
|
||
<swp-auto-id>Afstemnings-ID: <strong id="reconciliationId">KA-2025-12-29-01</strong> · oprettet automatisk</swp-auto-id>
|
||
</swp-card-body>
|
||
</swp-card>
|
||
|
||
<!-- Note -->
|
||
<swp-card>
|
||
<swp-card-header>
|
||
<swp-card-title>Note til difference</swp-card-title>
|
||
<swp-card-hint>Valgfrit</swp-card-hint>
|
||
</swp-card-header>
|
||
<swp-card-body>
|
||
<swp-note-field>
|
||
<textarea placeholder="Fx kassedifference, fejlslag, runding osv."></textarea>
|
||
</swp-note-field>
|
||
<swp-note-hint>Kan gøres obligatorisk ved difference over 100 kr.</swp-note-hint>
|
||
</swp-card-body>
|
||
</swp-card>
|
||
|
||
<!-- Godkendelse -->
|
||
<swp-card>
|
||
<swp-card-header>
|
||
<swp-card-title>Afslut dagen</swp-card-title>
|
||
</swp-card-header>
|
||
<swp-card-body>
|
||
<swp-approval-grid>
|
||
<swp-form-field>
|
||
<swp-form-label>Status</swp-form-label>
|
||
<swp-status-row>
|
||
<swp-status-badge class="draft">Kladde</swp-status-badge>
|
||
</swp-status-row>
|
||
</swp-form-field>
|
||
|
||
<swp-form-field>
|
||
<swp-form-label>Godkendt af (valgfrit)</swp-form-label>
|
||
<swp-form-input>
|
||
<select id="approver">
|
||
<option value="">Vælg...</option>
|
||
<option>Karina Knudsen</option>
|
||
<option>Butikschef</option>
|
||
</select>
|
||
</swp-form-input>
|
||
</swp-form-field>
|
||
|
||
<swp-checkbox-field>
|
||
<input type="checkbox" id="confirmCheckbox" />
|
||
<label for="confirmCheckbox">Jeg bekræfter, at kassen er talt op, og at tallene er indtastet efter bedste evne.</label>
|
||
</swp-checkbox-field>
|
||
</swp-approval-grid>
|
||
</swp-card-body>
|
||
<swp-card-footer>
|
||
<swp-btn class="secondary">Gem som kladde</swp-btn>
|
||
<swp-actions-right>
|
||
<swp-btn class="ghost">Fortryd</swp-btn>
|
||
<swp-btn class="primary" id="approveBtn" disabled>Godkend & lås</swp-btn>
|
||
</swp-actions-right>
|
||
</swp-card-footer>
|
||
</swp-card>
|
||
</div>
|
||
</div>
|
||
|
||
<swp-system-note>Systemet gemmer hvornår og af hvem der er godkendt – enkelt kontrolspor.</swp-system-note>
|
||
</swp-page-container>
|
||
|
||
<script>
|
||
// Set today's date
|
||
const dateInput = document.getElementById('reconciliationDate');
|
||
const today = new Date();
|
||
dateInput.value = today.toISOString().split('T')[0];
|
||
|
||
// Update reconciliation ID based on date
|
||
function updateReconciliationId() {
|
||
const date = new Date(dateInput.value);
|
||
const id = `KA-${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}-01`;
|
||
document.getElementById('reconciliationId').textContent = id;
|
||
}
|
||
dateInput.addEventListener('change', updateReconciliationId);
|
||
|
||
// Base values (from system)
|
||
const startBalance = 2000;
|
||
const cashSales = 3540;
|
||
|
||
// Format number as Danish currency
|
||
function formatNumber(num) {
|
||
return num.toLocaleString('da-DK', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
||
}
|
||
|
||
// Parse Danish number format
|
||
function parseNumber(str) {
|
||
if (!str) return 0;
|
||
return parseFloat(str.replace(/\./g, '').replace(',', '.')) || 0;
|
||
}
|
||
|
||
// Calculate expected cash and difference
|
||
function calculate() {
|
||
const payoutsInput = document.getElementById('payouts');
|
||
const toBankInput = document.getElementById('toBank');
|
||
const actualInput = document.getElementById('actualCash');
|
||
|
||
const payouts = parseNumber(payoutsInput.value);
|
||
const toBank = parseNumber(toBankInput.value);
|
||
const actual = parseNumber(actualInput.value);
|
||
|
||
// Forventet = start + salg - udbetalinger - til bank
|
||
const expectedCash = startBalance + cashSales - payouts - toBank;
|
||
document.getElementById('expectedCash').textContent = formatNumber(expectedCash);
|
||
|
||
// Difference
|
||
const box = document.getElementById('differenceBox');
|
||
const value = document.getElementById('differenceValue');
|
||
const diff = actual - expectedCash;
|
||
|
||
box.classList.remove('positive', 'negative', 'neutral');
|
||
|
||
if (actual === 0 && actualInput.value === '') {
|
||
value.textContent = '– kr';
|
||
box.classList.add('neutral');
|
||
} else if (diff > 0) {
|
||
value.textContent = '+' + formatNumber(diff) + ' kr';
|
||
box.classList.add('positive');
|
||
} else if (diff < 0) {
|
||
value.textContent = formatNumber(diff) + ' kr';
|
||
box.classList.add('negative');
|
||
} else {
|
||
value.textContent = '0,00 kr';
|
||
box.classList.add('neutral');
|
||
}
|
||
}
|
||
|
||
document.getElementById('payouts').addEventListener('input', calculate);
|
||
document.getElementById('toBank').addEventListener('input', calculate);
|
||
document.getElementById('actualCash').addEventListener('input', calculate);
|
||
|
||
// Enable approve button when checkbox is checked
|
||
const checkbox = document.getElementById('confirmCheckbox');
|
||
const approveBtn = document.getElementById('approveBtn');
|
||
|
||
checkbox.addEventListener('change', () => {
|
||
approveBtn.disabled = !checkbox.checked;
|
||
});
|
||
|
||
// Initial display
|
||
calculate();
|
||
</script>
|
||
</body>
|
||
</html>
|