Moving away from Azure Devops #1

Merged
Janus007 merged 113 commits from refac into master 2026-02-03 00:04:27 +01:00
14 changed files with 3492 additions and 281 deletions
Showing only changes of commit fac7754d7a - Show all commits

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

564
.workbench/spec-salary.html Normal file
View file

@ -0,0 +1,564 @@
<!doctype html>
<html lang="da">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Lønspecifikation Januar 2026 (2 sider)</title>
<style>
/* ===== Print setup ===== */
@page { size: A4; margin: 14mm; }
@media print {
.no-print { display: none !important; }
.page-break { break-after: page; page-break-after: always; }
a { color: inherit; text-decoration: none; }
}
/* ===== Base ===== */
:root{
--ink:#0f172a;
--muted:#475569;
--line:#e2e8f0;
--soft:#f8fafc;
--accent:#0ea5e9;
--accent-2:#22c55e;
}
*{ box-sizing:border-box; }
body{
margin:0;
font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
color:var(--ink);
background:#fff;
}
.sheet{
max-width: 210mm;
margin: 0 auto;
}
/* ===== Header ===== */
.hdr{
display:flex;
justify-content:space-between;
gap:16px;
padding: 14px 0 10px;
border-bottom: 2px solid var(--line);
margin-bottom: 12px;
}
.brand{
display:flex;
flex-direction:column;
gap:6px;
}
.title{
font-size: 20px;
font-weight: 800;
letter-spacing: .2px;
margin:0;
line-height:1.1;
}
.subtitle{
margin:0;
color:var(--muted);
font-size: 12px;
}
.meta{
text-align:right;
min-width: 260px;
}
.meta .pill{
display:inline-block;
font-size:12px;
padding:6px 10px;
border:1px solid var(--line);
border-radius:999px;
background:var(--soft);
margin-bottom:8px;
}
.meta .kv{
display:grid;
grid-template-columns: auto auto;
gap:4px 12px;
justify-content:end;
font-size:12px;
color:var(--muted);
}
.meta .kv b{ color:var(--ink); font-weight:600; }
/* ===== Blocks ===== */
.card{
border:1px solid var(--line);
border-radius: 14px;
overflow:hidden;
background:#fff;
margin-bottom: 12px;
}
.card .hd{
display:flex;
align-items:center;
justify-content:space-between;
padding: 10px 12px;
background: linear-gradient(0deg, var(--soft), #fff);
border-bottom: 1px solid var(--line);
}
.card .hd h2{
font-size: 13px;
margin:0;
letter-spacing:.2px;
text-transform: uppercase;
color:var(--muted);
}
.card .bd{ padding: 12px; }
.grid{
display:grid;
grid-template-columns: 1.2fr .8fr;
gap: 12px;
}
/* ===== Total ===== */
.total{
display:flex;
align-items:baseline;
justify-content:space-between;
gap:12px;
padding: 14px 14px;
border-radius: 14px;
border: 1px solid var(--line);
background: linear-gradient(135deg, rgba(14,165,233,.10), rgba(34,197,94,.08));
margin-bottom: 12px;
}
.total .label{
color:var(--muted);
font-size:12px;
text-transform:uppercase;
letter-spacing:.25px;
margin-bottom:6px;
}
.total .big{
font-size: 28px;
font-weight: 900;
margin:0;
line-height:1.05;
}
.total .big small{
font-size: 14px;
font-weight: 700;
color:var(--muted);
}
.badge{
display:inline-block;
font-size:11px;
padding:4px 8px;
border-radius:999px;
border:1px solid var(--line);
background:var(--soft);
color:var(--muted);
}
/* ===== Tables ===== */
table{
width:100%;
border-collapse: collapse;
font-size: 12px;
}
th, td{
padding: 8px 8px;
border-bottom:1px solid var(--line);
vertical-align:top;
}
th{
text-align:left;
color:var(--muted);
font-weight:700;
font-size:11px;
text-transform:uppercase;
letter-spacing:.2px;
background: var(--soft);
}
td.num, th.num{ text-align:right; }
tr:last-child td{ border-bottom:none; }
.note{
margin:8px 0 0;
color:var(--muted);
font-size:11px;
line-height:1.35;
}
/* ===== Footer ===== */
.ftr{
margin-top: 10px;
padding-top: 10px;
border-top:1px solid var(--line);
display:flex;
justify-content:space-between;
gap:12px;
font-size: 10.5px;
color:var(--muted);
}
/* ===== Ensure “side 1” content doesn't get split awkwardly ===== */
.avoid-break { break-inside: avoid; page-break-inside: avoid; }
</style>
</head>
<body>
<!-- ===================== PAGE 1: OVERBLIK ===================== -->
<div class="sheet">
<div class="hdr">
<div class="brand">
<p class="title">Lønspecifikation</p>
<p class="subtitle">Periode: <b>Januar 2026</b></p>
</div>
<div class="meta">
<div class="pill">Medarbejdernr.: <b>EMP-001</b></div>
<div class="kv">
<span>Medarbejder:</span><b>Emma Larsen</b>
<span>Afdeling:</span><b>Frisør</b>
<span>Ansættelse:</span><b>Fuldtid (37 t/uge)</b>
</div>
</div>
</div>
<section class="total avoid-break">
<div>
<div class="label">Bruttoløn (Januar 2026)</div>
<p class="big">34.063,50 <small>kr</small></p>
</div>
<div style="text-align:right">
<div><span class="badge">Side 1: Overblik</span></div>
<div style="margin-top:6px; color:var(--muted); font-size:12px; line-height:1.35">
Kort opsummering til udlevering.<br/>
Detaljer findes på side 2.
</div>
</div>
</section>
<section class="grid">
<div class="card avoid-break">
<div class="hd">
<h2>Samlet lønopgørelse</h2>
<span class="badge">Alle beløb i DKK</span>
</div>
<div class="bd">
<table>
<thead>
<tr>
<th>Løndel</th>
<th class="num">Beløb</th>
</tr>
</thead>
<tbody>
<tr>
<td>Grundløn inkl. overarbejde</td>
<td class="num">29.322,50 kr</td>
</tr>
<tr>
<td>Provision i alt</td>
<td class="num">3.685,00 kr</td>
</tr>
<tr>
<td>Tillæg i alt</td>
<td class="num">1.056,00 kr</td>
</tr>
<tr>
<td><b>Bruttoløn</b></td>
<td class="num"><b>34.063,50 kr</b></td>
</tr>
</tbody>
</table>
<p class="note">
(Hvis du senere vil have skat/AM-bidrag/nettoløn med, kan det tilføjes som ekstra blok her.)
</p>
</div>
</div>
<div class="card avoid-break">
<div class="hd">
<h2>Saldi</h2>
<span class="badge">Ved periodens slut</span>
</div>
<div class="bd">
<table>
<thead>
<tr>
<th>Type</th>
<th class="num">Optjent</th>
<th class="num">Afholdt</th>
<th class="num">Rest</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ferie (dage)</td>
<td class="num">18,5</td>
<td class="num">6,0</td>
<td class="num">12,5</td>
</tr>
<tr>
<td>Afspadsering (timer)</td>
<td class="num">12,0</td>
<td class="num">4,0</td>
<td class="num">8,0</td>
</tr>
</tbody>
</table>
<p class="note">Saldi er opgjort som angivet på lønspecifikationen.</p>
</div>
</div>
</section>
<section class="card avoid-break">
<div class="hd">
<h2>Hurtigt resumé</h2>
<span class="badge">Det vigtigste</span>
</div>
<div class="bd">
<table>
<thead>
<tr>
<th>Nøglepunkt</th>
<th class="num">Værdi</th>
</tr>
</thead>
<tbody>
<tr>
<td>Normaltimer</td>
<td class="num">148,0 t</td>
</tr>
<tr>
<td>Overarbejde</td>
<td class="num">7,0 t</td>
</tr>
<tr>
<td>Provision (services + produkter)</td>
<td class="num">3.685,00 kr</td>
</tr>
<tr>
<td>Tillæg (aften + lørdag + søndag)</td>
<td class="num">1.056,00 kr</td>
</tr>
</tbody>
</table>
</div>
</section>
<div class="ftr">
<div><b>Side 1/2</b> · Overblik</div>
<div style="text-align:right">Lønspecifikation · Januar 2026</div>
</div>
<div class="page-break"></div>
<!-- ===================== PAGE 2: DETALJER ===================== -->
<div class="hdr">
<div class="brand">
<p class="title">Lønspecifikation Detaljer</p>
<p class="subtitle">Periode: <b>Januar 2026</b> · Medarbejder: <b>Emma Larsen</b></p>
</div>
<div class="meta">
<div class="pill">Bruttoløn: <b>34.063,50 kr</b></div>
<div class="kv">
<span>Ansættelse:</span><b>Fuldtid (37 t/uge)</b>
<span>Afdeling:</span><b>Frisør</b>
<span>Medarb.nr.:</span><b>EMP-001</b>
</div>
</div>
</div>
<section class="card">
<div class="hd">
<h2>Arbejdstid pr. uge</h2>
<span class="badge">Normal + overtid</span>
</div>
<div class="bd">
<table>
<thead>
<tr>
<th>Uge</th>
<th class="num">Normaltimer</th>
<th class="num">Overtid</th>
<th class="num">Beløb</th>
</tr>
</thead>
<tbody>
<tr>
<td>Uge 1 (30. dec 5. jan)</td>
<td class="num">37,0 t</td>
<td class="num">2,0 t</td>
<td class="num">7.400,00 kr</td>
</tr>
<tr>
<td>Uge 2 (6. 12. jan)</td>
<td class="num">37,0 t</td>
<td class="num">3,5 t</td>
<td class="num">7.816,25 kr</td>
</tr>
<tr>
<td>Uge 3 (13. 19. jan)</td>
<td class="num">37,0 t</td>
<td class="num">0,0 t</td>
<td class="num">6.845,00 kr</td>
</tr>
<tr>
<td>Uge 4 (20. 26. jan)</td>
<td class="num">37,0 t</td>
<td class="num">1,5 t</td>
<td class="num">7.261,25 kr</td>
</tr>
<tr>
<td><b>I alt</b></td>
<td class="num"><b>148,0 t</b></td>
<td class="num"><b>7,0 t</b></td>
<td class="num"><b>29.322,50 kr</b></td>
</tr>
</tbody>
</table>
<p class="note">
Satser: Normal 185,00 kr/time. Overtid (50%) 277,50 kr/time.
</p>
</div>
</section>
<section class="card">
<div class="hd">
<h2>Provision</h2>
<span class="badge">Services & produkter</span>
</div>
<div class="bd">
<p class="note" style="margin-top:0">
<b>Services:</b> 15% af omsætning over minimum (220 kr/time).<br/>
<b>Produkter:</b> 10% af salg.
</p>
<table>
<thead>
<tr>
<th>Uge</th>
<th class="num">Service prov.</th>
<th class="num">Produkt prov.</th>
<th class="num">I alt</th>
</tr>
</thead>
<tbody>
<tr>
<td>Uge 1</td>
<td class="num">573,00 kr</td>
<td class="num">210,00 kr</td>
<td class="num">783,00 kr</td>
</tr>
<tr>
<td>Uge 2</td>
<td class="num">883,50 kr</td>
<td class="num">320,00 kr</td>
<td class="num">1.203,50 kr</td>
</tr>
<tr>
<td>Uge 3</td>
<td class="num">459,00 kr</td>
<td class="num">180,00 kr</td>
<td class="num">639,00 kr</td>
</tr>
<tr>
<td>Uge 4</td>
<td class="num">769,50 kr</td>
<td class="num">290,00 kr</td>
<td class="num">1.059,50 kr</td>
</tr>
<tr>
<td><b>I alt</b></td>
<td class="num"><b>2.685,00 kr</b></td>
<td class="num"><b>1.000,00 kr</b></td>
<td class="num"><b>3.685,00 kr</b></td>
</tr>
</tbody>
</table>
</div>
</section>
<section class="card">
<div class="hd">
<h2>Tillæg & fravær</h2>
<span class="badge">Opsummering</span>
</div>
<div class="bd">
<div class="grid" style="grid-template-columns: 1fr 1fr;">
<div>
<table>
<thead>
<tr>
<th>Tillæg</th>
<th class="num">Timer</th>
<th class="num">Beløb</th>
</tr>
</thead>
<tbody>
<tr>
<td>Aftentillæg (hverdage 1821)</td>
<td class="num">12,0</td>
<td class="num">336,00 kr</td>
</tr>
<tr>
<td>Lørdagstillæg (før kl. 14)</td>
<td class="num">16,0</td>
<td class="num">720,00 kr</td>
</tr>
<tr>
<td>Søndagstillæg</td>
<td class="num">0,0</td>
<td class="num">0,00 kr</td>
</tr>
<tr>
<td><b>Tillæg i alt</b></td>
<td class="num"></td>
<td class="num"><b>1.056,00 kr</b></td>
</tr>
</tbody>
</table>
</div>
<div>
<table>
<thead>
<tr>
<th>Fravær</th>
<th class="num">Dage</th>
<th class="num">Beløb</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ferie med løn</td>
<td class="num">0</td>
<td class="num">0,00 kr</td>
</tr>
<tr>
<td>Sygdom</td>
<td class="num">0</td>
<td class="num">0,00 kr</td>
</tr>
<tr>
<td>Barns sygedag</td>
<td class="num">0</td>
<td class="num">0,00 kr</td>
</tr>
</tbody>
</table>
<p class="note">Ingen fravær registreret i perioden.</p>
</div>
</div>
</div>
</section>
<div class="ftr">
<div><b>Side 2/2</b> · Detaljer</div>
<div style="text-align:right">Lønspecifikation · Januar 2026</div>
</div>
<div class="no-print" style="margin:12px 0; color:var(--muted); font-size:12px;">
Tip: I Chrome/Edge: <b>Ctrl/Cmd + P</b> → Destination: <b>Gem som PDF</b> → slå “Headers and footers” fra.
</div>
</div>
</body>
</html>

221
docs/design-system.md Normal file
View file

@ -0,0 +1,221 @@
# SWP Design System - UI/UX Dokumentation
## Oversigt
Dette dokument beskriver det komponent-baserede design system udviklet til Salon OS SaaS platformen gennem POC-udvikling. Systemet består af **150+ custom HTML elementer** med `swp-` prefix.
---
## Design Principper
- **Custom Elements**: Alle komponenter bruger semantiske `swp-*` tags
- **CSS Variables**: Theming via `--color-*` variabler (light/dark mode)
- **Responsive**: Mobile-first med grid breakpoints
- **Konsistent spacing**: 4px base unit (4, 8, 12, 16, 20, 24px)
---
## Farvepalette (CSS Variables)
```css
--color-surface: #fff / #1e1e1e
--color-background: #f5f5f5 / #121212
--color-border: #e0e0e0 / #333
--color-text: #333 / #e0e0e0
--color-text-secondary: #666 / #999
--color-teal: #00897b (primary)
--color-blue: #1976d2
--color-green: #43a047 (success)
--color-amber: #f59e0b (warning)
--color-red: #e53935 (error)
--color-purple: #8b5cf6
```
---
## Typografi
```css
--font-family: 'Poppins', sans-serif
--font-mono: 'JetBrains Mono', monospace
```
| Størrelse | Brug |
|-----------|------|
| 22px | Stat values |
| 16px | Page titles |
| 14px | Body text |
| 13px | Table cells, inputs |
| 12px | Labels, hints |
| 11px | Table headers (uppercase) |
---
## Komponent-katalog
### 1. Layout & Container
| Element | Beskrivelse |
|---------|-------------|
| `swp-page` | Hovedpage wrapper |
| `swp-page-container` | Max-width container (1400px) |
| `swp-card` | Kortkomponent med border og shadow |
| `swp-card-header` | Kortheader med titel |
| `swp-drawer` | Slide-in panel fra højre |
| `swp-drawer-overlay` | Mørk overlay bag drawer |
| `swp-two-columns` | To-kolonne layout |
### 2. Navigation
| Element | Beskrivelse |
|---------|-------------|
| `swp-topbar` | Sticky header bar |
| `swp-topbar-left/right` | Flex containers i topbar |
| `swp-page-title` | Sidetitel i topbar |
| `swp-back-link` | Tilbage-navigation med ikon |
| `swp-tabs` | Tab navigation |
| `swp-tab` | Enkelt tab |
### 3. Formularer
| Element | Beskrivelse |
|---------|-------------|
| `swp-form-field` | Wrapper for label + input |
| `swp-form-label` | Form label |
| `swp-form-input` | Input wrapper |
| `swp-form-row` | Horisontal gruppe af felter |
| `swp-form-hint` | Hjælpetekst under felt |
| `swp-toggle-slider` | On/off toggle |
| `swp-edit-section` | Redigerbar sektion |
| `swp-edit-row` | Label + værdi row |
### 4. Tabeller
| Element | Beskrivelse |
|---------|-------------|
| `swp-table` | Hovedtabel container |
| `swp-table-header` | Header row (grid) |
| `swp-table-body` | Body container |
| `swp-table-row` | Data row (grid) |
| `swp-th` | Header cell |
| `swp-td` | Data cell |
| `swp-table-footer` | Footer med pagination |
| `swp-row-arrow` | Klik-indikator pil |
### 5. Statistik
| Element | Beskrivelse |
|---------|-------------|
| `swp-stats-bar` | Grid af stat cards |
| `swp-stat-card` | Enkelt statistik kort |
| `swp-stat-value` | Stor tal (mono font) |
| `swp-stat-label` | Beskrivelse under tal |
| `swp-stat-change` | Ændring indikator (+/-) |
### 6. Søgning & Filtrering
| Element | Beskrivelse |
|---------|-------------|
| `swp-filter-bar` | Filterpanel |
| `swp-search-input` | Søgefelt med ikon |
| `swp-filter-group` | Label + select/input |
| `swp-filter-label` | Filter label |
### 7. Badges & Status
| Element | Beskrivelse | Klasser |
|---------|-------------|---------|
| `swp-status-badge` | Status indikator | `.paid`, `.pending`, `.credited` |
| `swp-payment-badge` | Betalingsmetode | `.card`, `.cash`, `.mobilepay` |
| `swp-tag` | Inline tag | `.vip`, `.new` |
### 8. Buttons
| Element | Beskrivelse | Klasser |
|---------|-------------|---------|
| `swp-btn` | Standard button | `.primary`, `.secondary`, `.danger` |
### 9. Charts (swp-charting)
| Element | Beskrivelse |
|---------|-------------|
| `swp-chart-card` | Chart wrapper kort |
| `swp-chart-header` | Titel + hint |
| `swp-chart-container` | Canvas container |
### 10. Specialiserede Komponenter
#### Kunde
- `swp-customer-avatar` - Rund avatar
- `swp-customer-cell` - Navn + telefon
- `swp-customer-header` - Profil header
#### Medarbejder
- `swp-employee-avatar` - Medarbejder billede
- `swp-employee-name` - Navn display
#### Faktura
- `swp-invoice-cell` - Fakturanummer
- `swp-datetime-cell` - Dato + tid
- `swp-amount-cell` - Beløb (højre-justeret)
#### Produkt
- `swp-variants-table` - Variant liste
- `swp-stock-display` - Lagerstatus
- `swp-margin-display` - Avance visning
#### Booking/AI
- `swp-gap-card` - Ledigt hul kort
- `swp-suggestion-item` - AI forslag
- `swp-optimization-score` - Score cirkel
---
## Pagination
```html
<swp-pagination>
<swp-page-btn><i class="ph ph-caret-left"></i></swp-page-btn>
<swp-page-btn class="active">1</swp-page-btn>
<swp-page-btn>2</swp-page-btn>
<swp-page-btn>...</swp-page-btn>
<swp-page-btn><i class="ph ph-caret-right"></i></swp-page-btn>
</swp-pagination>
```
---
## Ikoner
Bruger **Phosphor Icons** via CDN:
```html
<script src="https://unpkg.com/@phosphor-icons/web@2.1.1"></script>
<i class="ph ph-magnifying-glass"></i>
<i class="ph ph-caret-right"></i>
<i class="ph ph-credit-card"></i>
```
---
## POC Filer (Reference)
| Fil | Domæne |
|-----|--------|
| `poc-salg.html` | Salgsoversigt, fakturaer |
| `poc-customer-list.html` | Kundeliste |
| `poc-customer-detail.html` | Kundeprofil |
| `poc-employee.html` | Medarbejderprofil |
| `poc-produkt.html` | Produktdetaljer |
| `poc-gavekort.html` | Fordelskort |
| `poc-kasseafstemninger.html` | Kasseafstemning |
| `poc-rapport.html` | Rapporter |
| `poc-indstillinger.html` | Indstillinger |
---
## Næste Skridt: .NET Core Implementation
Når design systemet er dokumenteret, er næste fase at implementere:
1. Backend API endpoints
2. Database modeller
3. Razor/Blazor komponenter baseret på swp-* elementer

8
package-lock.json generated
View file

@ -10,7 +10,7 @@
"dependencies": {
"@novadi/core": "^0.6.0",
"@rollup/rollup-win32-x64-msvc": "^4.52.2",
"@sevenweirdpeople/swp-charting": "^0.2.1",
"@sevenweirdpeople/swp-charting": "^0.2.2",
"dayjs": "^1.11.19",
"fuse.js": "^7.1.0",
"json-diff-ts": "^4.8.2",
@ -1177,9 +1177,9 @@
]
},
"node_modules/@sevenweirdpeople/swp-charting": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@sevenweirdpeople/swp-charting/-/swp-charting-0.2.1.tgz",
"integrity": "sha512-QtY77Dyv4Vs/rWfBVSDTmuxgD4L8tGu4pmTF0l3i8HDwK6qtT2wEtH35UHD1RDFE1VtOGcnU0/dTdqjNWCqzxA==",
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/@sevenweirdpeople/swp-charting/-/swp-charting-0.2.2.tgz",
"integrity": "sha512-q9p7TOSMAq6I0t6jGEWpmjR7l2H8q8G0TnXbIpDutCz5a2JEqMDFe0NGBGcCwze2rvvRnRvCz8P2zGMQlHmphw==",
"license": "MIT"
},
"node_modules/@types/chai": {

View file

@ -43,7 +43,7 @@
"dependencies": {
"@novadi/core": "^0.6.0",
"@rollup/rollup-win32-x64-msvc": "^4.52.2",
"@sevenweirdpeople/swp-charting": "^0.2.1",
"@sevenweirdpeople/swp-charting": "^0.2.2",
"dayjs": "^1.11.19",
"fuse.js": "^7.1.0",
"json-diff-ts": "^4.8.2",

View file

@ -2266,6 +2266,152 @@
background: color-mix(in srgb, var(--color-teal) 15%, white);
color: var(--color-teal);
}
/* ==========================================
RATES DRAWER
========================================== */
swp-drawer-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.3);
z-index: 999;
}
swp-drawer-overlay.open {
display: block;
}
swp-rates-drawer {
display: none;
position: fixed;
top: 0;
right: 0;
bottom: 0;
width: 420px;
background: var(--color-surface);
box-shadow: -4px 0 20px rgba(0,0,0,0.15);
z-index: 1000;
flex-direction: column;
}
swp-rates-drawer.open {
display: flex;
}
swp-drawer-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 20px;
border-bottom: 1px solid var(--color-border);
}
swp-drawer-title {
font-size: 16px;
font-weight: 600;
}
swp-drawer-close {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 6px;
cursor: pointer;
color: var(--color-text-secondary);
transition: all 150ms ease;
}
swp-drawer-close:hover {
background: var(--color-background);
color: var(--color-text);
}
swp-drawer-body {
flex: 1;
overflow-y: auto;
padding: 16px 20px;
}
swp-rate-row {
display: grid;
grid-template-columns: 28px 1fr 100px;
align-items: center;
gap: 12px;
padding: 12px 0;
border-bottom: 1px solid var(--color-border);
}
swp-rate-row:last-child {
border-bottom: none;
}
swp-rate-row input[type="checkbox"] {
width: 18px;
height: 18px;
accent-color: var(--color-teal);
}
swp-rate-label {
font-size: 14px;
}
swp-rate-label.disabled {
opacity: 0.4;
}
swp-rate-input {
display: flex;
align-items: center;
gap: 4px;
font-size: 13px;
color: var(--color-text-secondary);
}
swp-rate-input input {
width: 70px;
padding: 6px 8px;
border: 1px solid var(--color-border);
border-radius: 4px;
font-size: 13px;
font-family: var(--font-mono);
text-align: right;
}
swp-rate-input.disabled input {
opacity: 0.4;
background: var(--color-background);
}
.btn-link {
background: none;
border: none;
color: var(--color-teal);
font-size: 13px;
cursor: pointer;
padding: 0;
}
.btn-link:hover {
text-decoration: underline;
}
swp-card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
swp-card-header swp-section-label {
margin-bottom: 0;
}
.mono {
font-family: var(--font-mono);
}
</style>
</head>
<body>
@ -2650,35 +2796,24 @@
<div class="grid-2">
<div>
<swp-card>
<swp-section-label>Grundløn</swp-section-label>
<swp-card-header>
<swp-section-label>Satser</swp-section-label>
<button class="btn-link" onclick="openRatesDrawer()">Rediger</button>
</swp-card-header>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>Timeløn</swp-edit-label>
<swp-edit-value contenteditable="true">185 kr/time</swp-edit-value>
<swp-edit-label>Normal (timeløn)</swp-edit-label>
<swp-edit-value class="mono">131,49 kr</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Overarbejde</swp-edit-label>
<swp-edit-value contenteditable="true">150%</swp-edit-value>
<swp-edit-label>Overarbejde (100%)</swp-edit-label>
<swp-edit-value class="mono">280,50 kr</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Weekendtillæg</swp-edit-label>
<swp-edit-value contenteditable="true">25%</swp-edit-value>
<swp-edit-label>Ferie m. løn</swp-edit-label>
<swp-edit-value class="mono">140,25 kr</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
<swp-toggle-row style="margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--color-border);">
<swp-toggle-label>ATP-bidrag</swp-toggle-label>
<swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
<swp-toggle-row>
<swp-toggle-label>Pension (arbejdsgiver)</swp-toggle-label>
<swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
</swp-card>
<swp-card>
@ -2686,56 +2821,74 @@
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>Minimum pr. time</swp-edit-label>
<swp-edit-value contenteditable="true">220 kr</swp-edit-value>
<swp-edit-value class="mono" contenteditable="true">220 kr</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>På services</swp-edit-label>
<swp-edit-value contenteditable="true">15%</swp-edit-value>
<swp-edit-value class="mono" contenteditable="true">15%</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>På produktsalg</swp-edit-label>
<swp-edit-value contenteditable="true">15%</swp-edit-value>
<swp-edit-value class="mono" contenteditable="true">15%</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
</swp-card>
<swp-card>
<swp-section-label>Tillæg</swp-section-label>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>8-21 Hverdage</swp-edit-label>
<swp-edit-value class="mono">28,03 kr</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>8-21 Lørdage</swp-edit-label>
<swp-edit-value class="mono">56,02 kr</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Søndag</swp-edit-label>
<swp-edit-value class="mono">112,07 kr</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
</swp-card>
</div>
<swp-card>
<swp-section-label>Lønhistorik</swp-section-label>
<swp-section-label>Lønspecifikationer</swp-section-label>
<swp-salary-history>
<table>
<thead>
<tr>
<th>Dato</th>
<th>Ændring</th>
<th>Ny værdi</th>
<th>Periode</th>
<th>Bruttoløn</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td class="mono">01.01.2025</td>
<td>Lønforhøjelse</td>
<td class="mono">185 kr/time</td>
<td>Januar 2026</td>
<td class="mono">34.063,50 kr</td>
<td><a href="poc-loenspecifikation.html" class="link">Vis</a></td>
</tr>
<tr>
<td class="mono">01.01.2024</td>
<td>Lønforhøjelse</td>
<td class="mono">175 kr/time</td>
<td>December 2025</td>
<td class="mono">31.845,00 kr</td>
<td><a href="poc-loenspecifikation.html" class="link">Vis</a></td>
</tr>
<tr>
<td class="mono">01.07.2023</td>
<td>Provision ændret</td>
<td class="mono">12%</td>
<td>November 2025</td>
<td class="mono">33.290,25 kr</td>
<td><a href="poc-loenspecifikation.html" class="link">Vis</a></td>
</tr>
<tr>
<td class="mono">01.01.2023</td>
<td>Lønforhøjelse</td>
<td class="mono">165 kr/time</td>
<td>Oktober 2025</td>
<td class="mono">32.156,75 kr</td>
<td><a href="poc-loenspecifikation.html" class="link">Vis</a></td>
</tr>
<tr>
<td class="mono">01.08.2019</td>
<td>Ansættelse</td>
<td class="mono">145 kr/time</td>
<td>September 2025</td>
<td class="mono">34.520,00 kr</td>
<td><a href="poc-loenspecifikation.html" class="link">Vis</a></td>
</tr>
</tbody>
</table>
@ -3884,5 +4037,114 @@
});
</script>
<!-- Rates Drawer -->
<swp-drawer-overlay id="rates-overlay" onclick="closeRatesDrawer()"></swp-drawer-overlay>
<swp-rates-drawer id="rates-drawer">
<swp-drawer-header>
<swp-drawer-title>Lønsatser</swp-drawer-title>
<swp-drawer-close onclick="closeRatesDrawer()">
<i class="ph ph-x"></i>
</swp-drawer-close>
</swp-drawer-header>
<swp-drawer-body>
<swp-section-label style="margin-bottom: 12px;">Grundsatser</swp-section-label>
<swp-rate-row>
<input type="checkbox" checked>
<swp-rate-label>Normal (timeløn)</swp-rate-label>
<swp-rate-input><input type="text" value="131,49"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox" checked>
<swp-rate-label>Overarbejde (100%)</swp-rate-label>
<swp-rate-input><input type="text" value="280,50"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox">
<swp-rate-label class="disabled">Kursus/skole</swp-rate-label>
<swp-rate-input class="disabled"><input type="text" value="140,25"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox">
<swp-rate-label class="disabled">Afspadsering</swp-rate-label>
<swp-rate-input class="disabled"><input type="text" value="140,25"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox">
<swp-rate-label class="disabled">Fri m. løn</swp-rate-label>
<swp-rate-input class="disabled"><input type="text" value="140,25"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox" checked>
<swp-rate-label>Ferie m. løn</swp-rate-label>
<swp-rate-input><input type="text" value="140,25"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox">
<swp-rate-label class="disabled">Kontor</swp-rate-label>
<swp-rate-input class="disabled"><input type="text" value="140,25"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox">
<swp-rate-label class="disabled">Barns 1. sygedag</swp-rate-label>
<swp-rate-input class="disabled"><input type="text" value="140,25"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox">
<swp-rate-label class="disabled">Barns hospitalsindlæggelse</swp-rate-label>
<swp-rate-input class="disabled"><input type="text" value="140,25"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox">
<swp-rate-label class="disabled">Barsel</swp-rate-label>
<swp-rate-input class="disabled"><input type="text" value="140,25"> kr</swp-rate-input>
</swp-rate-row>
<div style="margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--color-border);">
<swp-section-label style="margin-bottom: 12px;">Tillæg</swp-section-label>
<swp-rate-row>
<input type="checkbox" checked>
<swp-rate-label>8-21 Hverdage (udenfor arbejdstid)</swp-rate-label>
<swp-rate-input><input type="text" value="28,03"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox" checked>
<swp-rate-label>8-21 Lørdage (udenfor arbejdstid)</swp-rate-label>
<swp-rate-input><input type="text" value="56,02"> kr</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox" checked>
<swp-rate-label>Søndag</swp-rate-label>
<swp-rate-input><input type="text" value="112,07"> kr</swp-rate-input>
</swp-rate-row>
</div>
<div style="margin-top: 24px; padding-top: 16px; border-top: 1px solid var(--color-border);">
<swp-section-label style="margin-bottom: 12px;">Provisionsberegning</swp-section-label>
<swp-rate-row>
<input type="checkbox" checked>
<swp-rate-label>Provision på produktsalg</swp-rate-label>
<swp-rate-input><input type="text" value="15"> %</swp-rate-input>
</swp-rate-row>
<swp-rate-row>
<input type="checkbox" checked>
<swp-rate-label>Provision på servicesalg</swp-rate-label>
<swp-rate-input><input type="text" value="15"> %</swp-rate-input>
</swp-rate-row>
</div>
</swp-drawer-body>
</swp-rates-drawer>
<script>
function openRatesDrawer() {
document.getElementById('rates-overlay').classList.add('open');
document.getElementById('rates-drawer').classList.add('open');
}
function closeRatesDrawer() {
document.getElementById('rates-overlay').classList.remove('open');
document.getElementById('rates-drawer').classList.remove('open');
}
</script>
</body>
</html>

View file

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gavekort GC-A7X2-9KM4 - Salon OS</title>
<title>Fordelskort FK-A7X2-9KM4 - Salon OS</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="https://unpkg.com/@phosphor-icons/web@2.1.1"></script>
<style>
@ -1084,9 +1084,9 @@
<swp-topbar-left>
<swp-back-link onclick="location.href='poc-gavekort.html'">
<i class="ph ph-caret-left"></i>
Gavekort
Fordelskort
</swp-back-link>
<swp-page-title>GC-A7X2-9KM4</swp-page-title>
<swp-page-title>FK-A7X2-9KM4</swp-page-title>
</swp-topbar-left>
<swp-topbar-right>
</swp-topbar-right>
@ -1130,12 +1130,12 @@
<!-- Gift Card Details -->
<swp-card>
<swp-section-label>Gavekort info</swp-section-label>
<swp-section-label>Kortinfo</swp-section-label>
<swp-kv-list>
<swp-kv-row>
<swp-kv-label>Kode</swp-kv-label>
<swp-kv-value class="mono with-action">
GC-A7X2-9KM4
FK-A7X2-9KM4
<swp-copy-btn onclick="copyCode()">
<i class="ph ph-copy"></i>
</swp-copy-btn>
@ -1194,7 +1194,7 @@
<swp-td class="muted">15/1-24</swp-td>
<swp-td>
<swp-transaction-details>
<swp-transaction-type>Gavekort oprettet</swp-transaction-type>
<swp-transaction-type>Kort oprettet</swp-transaction-type>
<swp-transaction-meta>
<a href="#">Faktura #1652</a> · <a href="#">Signe Larsen</a>
</swp-transaction-meta>
@ -1226,7 +1226,7 @@
</swp-recipient-row>
<swp-send-btn id="openEmailDrawerAlt">
<i class="ph ph-paper-plane-tilt"></i>
Send gavekort på email
Send fordelskort på email
</swp-send-btn>
</swp-card>
@ -1254,10 +1254,10 @@
<swp-email-icon>
<i class="ph ph-gift"></i>
</swp-email-icon>
<swp-email-title>Du har modtaget et gavekort!</swp-email-title>
<swp-email-title>Du har modtaget et fordelskort!</swp-email-title>
<swp-giftcard-visual>
<swp-giftcard-amount>500 DKK</swp-giftcard-amount>
<swp-giftcard-code-display>GC-A7X2-9KM4</swp-giftcard-code-display>
<swp-giftcard-code-display>FK-A7X2-9KM4</swp-giftcard-code-display>
</swp-giftcard-visual>
<swp-email-message id="previewMessage">Din besked vises her...</swp-email-message>
<swp-email-sender>
@ -1276,7 +1276,7 @@
<!-- Send Email Drawer -->
<swp-drawer id="emailDrawer">
<swp-drawer-header>
<swp-drawer-title>Send gavekort</swp-drawer-title>
<swp-drawer-title>Send fordelskort</swp-drawer-title>
<swp-drawer-close id="closeEmailDrawer">
<i class="ph ph-x"></i>
</swp-drawer-close>
@ -1311,7 +1311,7 @@
<!-- Add Value Drawer -->
<swp-drawer id="addValueDrawer">
<swp-drawer-header>
<swp-drawer-title>Juster gavekort</swp-drawer-title>
<swp-drawer-title>Juster fordelskort</swp-drawer-title>
<swp-drawer-close id="closeAddValueDrawer">
<i class="ph ph-x"></i>
</swp-drawer-close>
@ -1417,7 +1417,7 @@
// Copy code to clipboard
function copyCode() {
navigator.clipboard.writeText('GC-A7X2-9KM4').then(() => {
navigator.clipboard.writeText('FK-A7X2-9KM4').then(() => {
alert('Kode kopieret!');
});
}

View file

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Gavekort - Salon OS</title>
<title>Fordelskort - Salon OS</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="https://unpkg.com/@phosphor-icons/web@2.1.1"></script>
<style>
@ -802,12 +802,12 @@
<!-- Topbar -->
<swp-topbar>
<swp-topbar-left>
<swp-page-title>Gavekort</swp-page-title>
<swp-page-title>Fordelskort</swp-page-title>
</swp-topbar-left>
<swp-topbar-right>
<swp-btn class="primary" id="openCreateDrawer">
<i class="ph ph-plus"></i>
Opret gavekort
Opret fordelskort
</swp-btn>
</swp-topbar-right>
</swp-topbar>
@ -817,7 +817,7 @@
<swp-stats-bar>
<swp-stat-card class="highlight">
<swp-stat-value>47</swp-stat-value>
<swp-stat-label>Aktive gavekort</swp-stat-label>
<swp-stat-label>Aktive fordelskort</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value>23.500 DKK</swp-stat-value>
@ -863,7 +863,7 @@
<!-- Table -->
<swp-table>
<swp-table-header>
<swp-th>Gavekort</swp-th>
<swp-th>Fordelskort</swp-th>
<swp-th>Modtager</swp-th>
<swp-th class="right">Original</swp-th>
<swp-th>Saldo</swp-th>
@ -875,7 +875,7 @@
<swp-table-row onclick="location.href='poc-gavekort-detail.html'">
<swp-td>
<swp-giftcard-cell>
<swp-giftcard-code>GC-A7X2-9KM4</swp-giftcard-code>
<swp-giftcard-code>FK-A7X2-9KM4</swp-giftcard-code>
<swp-giftcard-date>Oprettet 15. jan 2024</swp-giftcard-date>
</swp-giftcard-cell>
</swp-td>
@ -902,7 +902,7 @@
<swp-table-row>
<swp-td>
<swp-giftcard-cell>
<swp-giftcard-code>GC-B3K9-2LM7</swp-giftcard-code>
<swp-giftcard-code>FK-B3K9-2LM7</swp-giftcard-code>
<swp-giftcard-date>Oprettet 20. dec 2024</swp-giftcard-date>
</swp-giftcard-cell>
</swp-td>
@ -928,7 +928,7 @@
<swp-table-row>
<swp-td>
<swp-giftcard-cell>
<swp-giftcard-code>GC-C5P1-8NQ3</swp-giftcard-code>
<swp-giftcard-code>FK-C5P1-8NQ3</swp-giftcard-code>
<swp-giftcard-date>Oprettet 10. nov 2024</swp-giftcard-date>
</swp-giftcard-cell>
</swp-td>
@ -955,7 +955,7 @@
<swp-table-row>
<swp-td>
<swp-giftcard-cell>
<swp-giftcard-code>GC-D2R4-6TY9</swp-giftcard-code>
<swp-giftcard-code>FK-D2R4-6TY9</swp-giftcard-code>
<swp-giftcard-date>Oprettet 5. sep 2024</swp-giftcard-date>
</swp-giftcard-cell>
</swp-td>
@ -982,7 +982,7 @@
<swp-table-row>
<swp-td>
<swp-giftcard-cell>
<swp-giftcard-code>GC-E8W3-4VX1</swp-giftcard-code>
<swp-giftcard-code>FK-E8W3-4VX1</swp-giftcard-code>
<swp-giftcard-date>Oprettet 1. jun 2024</swp-giftcard-date>
</swp-giftcard-cell>
</swp-td>
@ -1008,7 +1008,7 @@
<swp-table-row>
<swp-td>
<swp-giftcard-cell>
<swp-giftcard-code>GC-F9Q7-3WK5</swp-giftcard-code>
<swp-giftcard-code>FK-F9Q7-3WK5</swp-giftcard-code>
<swp-giftcard-date>Oprettet 28. dec 2024</swp-giftcard-date>
</swp-giftcard-cell>
</swp-td>
@ -1033,7 +1033,7 @@
</swp-table-row>
</swp-table-body>
<swp-table-footer>
<span>Viser 6 af 47 gavekort</span>
<span>Viser 6 af 47 fordelskort</span>
<span>Side 1 af 8</span>
</swp-table-footer>
</swp-table>
@ -1045,7 +1045,7 @@
<!-- Create Gift Card Drawer -->
<swp-drawer id="createDrawer">
<swp-drawer-header>
<swp-drawer-title>Opret gavekort</swp-drawer-title>
<swp-drawer-title>Opret fordelskort</swp-drawer-title>
<swp-drawer-close id="closeDrawer">
<i class="ph ph-x"></i>
</swp-drawer-close>
@ -1053,9 +1053,9 @@
<swp-drawer-content>
<swp-form-field>
<swp-form-label>Gavekortkode</swp-form-label>
<swp-form-label>Kortkode</swp-form-label>
<swp-input-group>
<input type="text" id="giftcardCode" class="mono" value="GC-K8M2-5NP7" readonly />
<input type="text" id="giftcardCode" class="mono" value="FK-K8M2-5NP7" readonly />
<button type="button" id="generateCode">
<i class="ph ph-arrows-clockwise"></i>
Ny kode
@ -1116,7 +1116,7 @@
<swp-drawer-footer>
<swp-btn class="secondary" id="cancelCreate">Annuller</swp-btn>
<swp-btn class="primary" id="saveGiftcard">Opret gavekort</swp-btn>
<swp-btn class="primary" id="saveGiftcard">Opret fordelskort</swp-btn>
</swp-drawer-footer>
</swp-drawer>
@ -1156,7 +1156,7 @@
// Generate random code
function generateCode() {
const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
let code = 'GC-';
let code = 'FK-';
for (let i = 0; i < 4; i++) {
code += chars.charAt(Math.floor(Math.random() * chars.length));
}

View file

@ -3370,6 +3370,118 @@ Tak for din handel!</swp-edit-textarea>
</swp-module-card>
</swp-modules-grid>
</swp-modules-section>
<!-- Integrationer sektion -->
<swp-modules-section>
<swp-modules-header>
<swp-modules-title>
<i class="ph ph-plugs-connected"></i>
Integrationer
</swp-modules-title>
</swp-modules-header>
<swp-modules-grid>
<!-- Sygeforsikring "danmark" -->
<swp-module-card class="featured">
<swp-module-header>
<swp-module-icon class="green">
<i class="ph ph-heart-half"></i>
</swp-module-icon>
<swp-module-info>
<swp-module-title>Sygeforsikring "danmark"</swp-module-title>
<swp-module-desc>Gør det nemt for dine kunder at få tilskud. Send automatisk kvitteringer til "danmark" så kunderne får deres penge tilbage uden selv at løfte en finger.</swp-module-desc>
</swp-module-info>
<swp-module-toggle>
<swp-toggle-slider data-value="no">
<swp-toggle-option>Til</swp-toggle-option>
<swp-toggle-option>Fra</swp-toggle-option>
</swp-toggle-slider>
</swp-module-toggle>
</swp-module-header>
<swp-module-features>
<swp-module-feature>
<i class="ph ph-check-circle"></i>
<span>Automatisk indsendelse af kvitteringer</span>
</swp-module-feature>
<swp-module-feature>
<i class="ph ph-check-circle"></i>
<span>Direkte integration via API</span>
</swp-module-feature>
<swp-module-feature>
<i class="ph ph-check-circle"></i>
<span>Kunden får tilskud uden besvær</span>
</swp-module-feature>
<swp-module-feature>
<i class="ph ph-check-circle"></i>
<span>Øget kundetilfredshed</span>
</swp-module-feature>
</swp-module-features>
<swp-module-stats>
<swp-module-stat>
<swp-module-stat-value>2.1M</swp-module-stat-value>
<swp-module-stat-label>Medlemmer i DK</swp-module-stat-label>
</swp-module-stat>
<swp-module-stat>
<swp-module-stat-value>100%</swp-module-stat-value>
<swp-module-stat-label>Automatiseret</swp-module-stat-label>
</swp-module-stat>
<swp-module-stat>
<swp-module-stat-value>0 kr</swp-module-stat-value>
<swp-module-stat-label>Ekstra gebyr</swp-module-stat-label>
</swp-module-stat>
</swp-module-stats>
<swp-module-footer>
<swp-module-tags>
<swp-module-tag class="included">Inkluderet</swp-module-tag>
</swp-module-tags>
<swp-btn class="small primary">Opsæt integration</swp-btn>
</swp-module-footer>
</swp-module-card>
<!-- Kalenderintegration -->
<swp-module-card>
<swp-module-header>
<swp-module-icon class="blue">
<i class="ph ph-calendar-check"></i>
</swp-module-icon>
<swp-module-info>
<swp-module-title>Kalenderintegration</swp-module-title>
<swp-module-desc>Få dine bookinger synkroniseret til din private kalender automatisk. Se alle aftaler samlet ét sted - også når du er offline.</swp-module-desc>
</swp-module-info>
<swp-module-toggle>
<swp-toggle-slider data-value="yes">
<swp-toggle-option>Til</swp-toggle-option>
<swp-toggle-option>Fra</swp-toggle-option>
</swp-toggle-slider>
</swp-module-toggle>
</swp-module-header>
<swp-module-features>
<swp-module-feature>
<i class="ph ph-check-circle"></i>
<span>Google Kalender</span>
</swp-module-feature>
<swp-module-feature>
<i class="ph ph-check-circle"></i>
<span>Apple iCloud Kalender</span>
</swp-module-feature>
<swp-module-feature>
<i class="ph ph-check-circle"></i>
<span>Microsoft Outlook</span>
</swp-module-feature>
<swp-module-feature>
<i class="ph ph-check-circle"></i>
<span>Tovejs-synkronisering</span>
</swp-module-feature>
</swp-module-features>
<swp-module-footer>
<swp-module-tags>
<swp-module-tag class="included">Inkluderet</swp-module-tag>
</swp-module-tags>
<swp-btn class="small secondary">Indstillinger</swp-btn>
</swp-module-footer>
</swp-module-card>
</swp-modules-grid>
</swp-modules-section>
</swp-tab-content>
<!-- ==========================================

View file

@ -123,7 +123,7 @@
<swp-page-header>
<swp-page-title>
<h1>Abonnement & Konto</h1>
<p>Administrer dit abonnement, brugere og betalingsinfo</p>
<p>Administrer dit abonnement og betalingsinfo</p>
</swp-page-title>
</swp-page-header>
@ -261,208 +261,6 @@
</swp-plan-grid>
</swp-section>
<!-- ==========================================
USERS SECTION
========================================== -->
<swp-section>
<swp-section-header>
<swp-section-title>
<i class="ph ph-users"></i>
Brugere
</swp-section-title>
</swp-section-header>
<swp-users-header>
<swp-users-count>
<strong>5 af 8</strong> brugere
<swp-users-progress>
<swp-users-progress-bar style="width: 62.5%"></swp-users-progress-bar>
</swp-users-progress>
</swp-users-count>
<swp-btn class="primary">
<i class="ph ph-user-plus"></i>
Inviter bruger
</swp-btn>
</swp-users-header>
<swp-table-card>
<swp-table>
<swp-table-header>
<swp-table-row>
<swp-table-cell>Bruger</swp-table-cell>
<swp-table-cell>Rolle</swp-table-cell>
<swp-table-cell>Status</swp-table-cell>
<swp-table-cell>Sidst aktiv</swp-table-cell>
<swp-table-cell></swp-table-cell>
</swp-table-row>
</swp-table-header>
<swp-table-body>
<!-- User 1 - Owner -->
<swp-table-row>
<swp-table-cell>
<swp-user-info>
<swp-user-avatar>MJ</swp-user-avatar>
<swp-user-details>
<swp-user-name>Maria Jensen</swp-user-name>
<swp-user-email>maria@salonbeauty.dk</swp-user-email>
</swp-user-details>
</swp-user-info>
</swp-table-cell>
<swp-table-cell>
<swp-role-badge class="owner">Ejer</swp-role-badge>
</swp-table-cell>
<swp-table-cell>
<swp-status-badge class="active">
<swp-status-dot></swp-status-dot>
Aktiv
</swp-status-badge>
</swp-table-cell>
<swp-table-cell>I dag, 14:32</swp-table-cell>
<swp-table-cell>
<swp-table-actions>
<swp-icon-btn title="Rediger">
<i class="ph ph-pencil"></i>
</swp-icon-btn>
</swp-table-actions>
</swp-table-cell>
</swp-table-row>
<!-- User 2 - Admin -->
<swp-table-row>
<swp-table-cell>
<swp-user-info>
<swp-user-avatar class="purple">AS</swp-user-avatar>
<swp-user-details>
<swp-user-name>Anna Sørensen</swp-user-name>
<swp-user-email>anna@salonbeauty.dk</swp-user-email>
</swp-user-details>
</swp-user-info>
</swp-table-cell>
<swp-table-cell>
<swp-role-badge class="admin">Admin</swp-role-badge>
</swp-table-cell>
<swp-table-cell>
<swp-status-badge class="active">
<swp-status-dot></swp-status-dot>
Aktiv
</swp-status-badge>
</swp-table-cell>
<swp-table-cell>I dag, 12:15</swp-table-cell>
<swp-table-cell>
<swp-table-actions>
<swp-icon-btn title="Rediger">
<i class="ph ph-pencil"></i>
</swp-icon-btn>
<swp-icon-btn class="danger" title="Fjern bruger">
<i class="ph ph-trash"></i>
</swp-icon-btn>
</swp-table-actions>
</swp-table-cell>
</swp-table-row>
<!-- User 3 -->
<swp-table-row>
<swp-table-cell>
<swp-user-info>
<swp-user-avatar class="blue">LP</swp-user-avatar>
<swp-user-details>
<swp-user-name>Louise Pedersen</swp-user-name>
<swp-user-email>louise@salonbeauty.dk</swp-user-email>
</swp-user-details>
</swp-user-info>
</swp-table-cell>
<swp-table-cell>
<swp-role-badge>Medarbejder</swp-role-badge>
</swp-table-cell>
<swp-table-cell>
<swp-status-badge class="active">
<swp-status-dot></swp-status-dot>
Aktiv
</swp-status-badge>
</swp-table-cell>
<swp-table-cell>I går, 17:45</swp-table-cell>
<swp-table-cell>
<swp-table-actions>
<swp-icon-btn title="Rediger">
<i class="ph ph-pencil"></i>
</swp-icon-btn>
<swp-icon-btn class="danger" title="Fjern bruger">
<i class="ph ph-trash"></i>
</swp-icon-btn>
</swp-table-actions>
</swp-table-cell>
</swp-table-row>
<!-- User 4 -->
<swp-table-row>
<swp-table-cell>
<swp-user-info>
<swp-user-avatar class="amber">KN</swp-user-avatar>
<swp-user-details>
<swp-user-name>Katrine Nielsen</swp-user-name>
<swp-user-email>katrine@salonbeauty.dk</swp-user-email>
</swp-user-details>
</swp-user-info>
</swp-table-cell>
<swp-table-cell>
<swp-role-badge>Medarbejder</swp-role-badge>
</swp-table-cell>
<swp-table-cell>
<swp-status-badge class="active">
<swp-status-dot></swp-status-dot>
Aktiv
</swp-status-badge>
</swp-table-cell>
<swp-table-cell>27. dec, 09:30</swp-table-cell>
<swp-table-cell>
<swp-table-actions>
<swp-icon-btn title="Rediger">
<i class="ph ph-pencil"></i>
</swp-icon-btn>
<swp-icon-btn class="danger" title="Fjern bruger">
<i class="ph ph-trash"></i>
</swp-icon-btn>
</swp-table-actions>
</swp-table-cell>
</swp-table-row>
<!-- User 5 - Invited -->
<swp-table-row>
<swp-table-cell>
<swp-user-info>
<swp-user-avatar class="purple">SH</swp-user-avatar>
<swp-user-details>
<swp-user-name>Sofie Hansen</swp-user-name>
<swp-user-email>sofie@salonbeauty.dk</swp-user-email>
</swp-user-details>
</swp-user-info>
</swp-table-cell>
<swp-table-cell>
<swp-role-badge>Medarbejder</swp-role-badge>
</swp-table-cell>
<swp-table-cell>
<swp-status-badge class="invited">
<swp-status-dot></swp-status-dot>
Invitation sendt
</swp-status-badge>
</swp-table-cell>
<swp-table-cell>-</swp-table-cell>
<swp-table-cell>
<swp-table-actions>
<swp-icon-btn title="Send invitation igen">
<i class="ph ph-paper-plane-tilt"></i>
</swp-icon-btn>
<swp-icon-btn class="danger" title="Annuller invitation">
<i class="ph ph-x"></i>
</swp-icon-btn>
</swp-table-actions>
</swp-table-cell>
</swp-table-row>
</swp-table-body>
</swp-table>
</swp-table-card>
</swp-section>
<!-- ==========================================
BILLING SECTION
========================================== -->

View file

@ -1650,7 +1650,7 @@
<i class="ph ph-users"></i>
<span>Kunder</span>
</swp-side-menu-item>
<swp-side-menu-item onclick="location.href='poc-employee.html'" data-tooltip="Medarbejdere">
<swp-side-menu-item onclick="location.href='poc-medarbejdere.html'" data-tooltip="Medarbejdere">
<i class="ph ph-user"></i>
<span>Medarbejdere</span>
</swp-side-menu-item>

View file

@ -0,0 +1,533 @@
<!doctype html>
<html lang="da">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Lønspecifikation Januar 2026</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
/* ===== Print setup ===== */
@page { size: A4; margin: 14mm; }
@media print {
.no-print { display: none !important; }
.page-break { break-after: page; page-break-after: always; }
a { color: inherit; text-decoration: none; }
}
/* ===== Base ===== */
:root {
--ink: #0f172a;
--muted: #475569;
--line: #e2e8f0;
--soft: #f8fafc;
--accent: #0ea5e9;
--accent-2: #22c55e;
--font-mono: 'JetBrains Mono', monospace;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
color: var(--ink);
background: #fff;
}
.sheet {
max-width: 210mm;
margin: 0 auto;
}
/* ===== Header ===== */
.hdr {
display: flex;
justify-content: space-between;
gap: 16px;
padding: 14px 0 10px;
border-bottom: 2px solid var(--line);
margin-bottom: 12px;
}
.brand {
display: flex;
flex-direction: column;
gap: 6px;
}
.title {
font-size: 20px;
font-weight: 800;
letter-spacing: .2px;
margin: 0;
line-height: 1.1;
}
.subtitle {
margin: 0;
color: var(--muted);
font-size: 12px;
}
.meta {
text-align: right;
min-width: 260px;
}
.meta .pill {
display: inline-block;
font-size: 12px;
padding: 6px 10px;
border: 1px solid var(--line);
border-radius: 999px;
background: var(--soft);
margin-bottom: 8px;
}
.meta .kv {
display: grid;
grid-template-columns: auto auto;
gap: 4px 12px;
justify-content: end;
font-size: 12px;
color: var(--muted);
}
.meta .kv b { color: var(--ink); font-weight: 600; }
/* ===== Blocks ===== */
.card {
border: 1px solid var(--line);
border-radius: 14px;
overflow: hidden;
background: #fff;
margin-bottom: 12px;
}
.card .hd {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 12px;
background: linear-gradient(0deg, var(--soft), #fff);
border-bottom: 1px solid var(--line);
}
.card .hd h2 {
font-size: 13px;
margin: 0;
letter-spacing: .2px;
text-transform: uppercase;
color: var(--muted);
}
.card .bd { padding: 12px; }
.grid {
display: grid;
grid-template-columns: 1.2fr .8fr;
gap: 12px;
}
/* ===== Total ===== */
.total {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
padding: 14px 14px;
border-radius: 14px;
border: 1px solid var(--line);
background: var(--soft);
margin-bottom: 12px;
}
.total .label {
color: var(--muted);
font-size: 12px;
text-transform: uppercase;
letter-spacing: .25px;
margin-bottom: 6px;
}
.total .big {
font-size: 28px;
font-weight: 900;
font-family: var(--font-mono);
margin: 0;
line-height: 1.05;
}
.total .big small {
font-size: 14px;
font-weight: 700;
color: var(--muted);
}
.badge {
display: inline-block;
font-size: 11px;
padding: 4px 8px;
border-radius: 999px;
border: 1px solid var(--line);
background: var(--soft);
color: var(--muted);
}
/* ===== Tables ===== */
table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
}
th, td {
padding: 8px 8px;
border-bottom: 1px solid var(--line);
vertical-align: top;
}
th {
text-align: left;
color: var(--muted);
font-weight: 700;
font-size: 11px;
text-transform: uppercase;
letter-spacing: .2px;
background: var(--soft);
}
td.num, th.num { text-align: right; }
td.num { font-family: var(--font-mono); }
tr:last-child td { border-bottom: none; }
.note {
margin: 8px 0 0;
color: var(--muted);
font-size: 11px;
line-height: 1.35;
}
/* ===== Footer ===== */
.ftr {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid var(--line);
display: flex;
justify-content: space-between;
gap: 12px;
font-size: 10.5px;
color: var(--muted);
}
/* ===== Ensure content doesn't get split awkwardly ===== */
.avoid-break { break-inside: avoid; page-break-inside: avoid; }
</style>
</head>
<body>
<!-- ===================== PAGE 1: OVERBLIK ===================== -->
<div class="sheet">
<div class="hdr">
<div class="brand">
<p class="title">Lønspecifikation</p>
<p class="subtitle">Periode: <b>Januar 2026</b></p>
</div>
<div class="meta">
<div class="pill">Medarbejdernr.: <b>EMP-001</b></div>
<div class="kv">
<span>Medarbejder:</span><b>Emma Larsen</b>
<span>Afdeling:</span><b>Frisør</b>
<span>Ansættelse:</span><b>Fuldtid (37 t/uge)</b>
</div>
</div>
</div>
<section class="total avoid-break">
<div>
<div class="label">Bruttoløn (Januar 2026)</div>
<p class="big">34.063,50 <small>kr</small></p>
</div>
</section>
<section class="grid">
<div class="card avoid-break">
<div class="hd">
<h2>Samlet lønopgørelse</h2>
</div>
<div class="bd">
<table>
<thead>
<tr>
<th>Løndel</th>
<th class="num">Beløb</th>
</tr>
</thead>
<tbody>
<tr>
<td>Grundløn inkl. overarbejde</td>
<td class="num">29.322,50 kr</td>
</tr>
<tr>
<td>Provision i alt</td>
<td class="num">3.685,00 kr</td>
</tr>
<tr>
<td>Tillæg i alt</td>
<td class="num">1.056,00 kr</td>
</tr>
<tr>
<td><b>Bruttoløn</b></td>
<td class="num"><b>34.063,50 kr</b></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card avoid-break">
<div class="hd">
<h2>Saldi</h2>
</div>
<div class="bd">
<table>
<thead>
<tr>
<th>Type</th>
<th class="num">Optjent</th>
<th class="num">Afholdt</th>
<th class="num">Rest</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ferie (dage)</td>
<td class="num">18,5</td>
<td class="num">6,0</td>
<td class="num">12,5</td>
</tr>
<tr>
<td>Afspadsering (timer)</td>
<td class="num">12,0</td>
<td class="num">4,0</td>
<td class="num">8,0</td>
</tr>
</tbody>
</table>
<p class="note">Saldi er opgjort som angivet på lønspecifikationen.</p>
</div>
</div>
</section>
<section class="card avoid-break">
<div class="hd">
<h2>Hurtigt resumé</h2>
</div>
<div class="bd">
<table>
<thead>
<tr>
<th>Nøglepunkt</th>
<th class="num">Værdi</th>
</tr>
</thead>
<tbody>
<tr>
<td>Normaltimer</td>
<td class="num">148,0 t</td>
</tr>
<tr>
<td>Overarbejde</td>
<td class="num">7,0 t</td>
</tr>
<tr>
<td>Provision (services + produkter)</td>
<td class="num">3.685,00 kr</td>
</tr>
<tr>
<td>Tillæg (aften + lørdag + søndag)</td>
<td class="num">1.056,00 kr</td>
</tr>
</tbody>
</table>
</div>
</section>
<div class="ftr">
<div>Overblik</div>
<div style="text-align:right">Lønspecifikation · Januar 2026</div>
</div>
<div class="page-break"></div>
<!-- ===================== PAGE 2: DETALJER ===================== -->
<section class="card">
<div class="hd">
<h2>Arbejdstid pr. uge</h2>
</div>
<div class="bd">
<table>
<thead>
<tr>
<th>Uge</th>
<th class="num">Normaltimer</th>
<th class="num">Overtid</th>
<th class="num">Beløb</th>
</tr>
</thead>
<tbody>
<tr>
<td>Uge 1 (30. dec 5. jan)</td>
<td class="num">37,0 t</td>
<td class="num">2,0 t</td>
<td class="num">7.400,00 kr</td>
</tr>
<tr>
<td>Uge 2 (6. 12. jan)</td>
<td class="num">37,0 t</td>
<td class="num">3,5 t</td>
<td class="num">7.816,25 kr</td>
</tr>
<tr>
<td>Uge 3 (13. 19. jan)</td>
<td class="num">37,0 t</td>
<td class="num">0,0 t</td>
<td class="num">6.845,00 kr</td>
</tr>
<tr>
<td>Uge 4 (20. 26. jan)</td>
<td class="num">37,0 t</td>
<td class="num">1,5 t</td>
<td class="num">7.261,25 kr</td>
</tr>
<tr>
<td><b>I alt</b></td>
<td class="num"><b>148,0 t</b></td>
<td class="num"><b>7,0 t</b></td>
<td class="num"><b>29.322,50 kr</b></td>
</tr>
</tbody>
</table>
<p class="note">
Satser: Normal 185,00 kr/time. Overtid (50%) 277,50 kr/time.
</p>
</div>
</section>
<section class="card">
<div class="hd">
<h2>Provision</h2>
</div>
<div class="bd">
<p class="note" style="margin-top:0">
<b>Services:</b> 15% af omsætning over minimum (220 kr/time).<br/>
<b>Produkter:</b> 10% af salg.
</p>
<table>
<thead>
<tr>
<th>Uge</th>
<th class="num">Service prov.</th>
<th class="num">Produkt prov.</th>
<th class="num">I alt</th>
</tr>
</thead>
<tbody>
<tr>
<td>Uge 1</td>
<td class="num">573,00 kr</td>
<td class="num">210,00 kr</td>
<td class="num">783,00 kr</td>
</tr>
<tr>
<td>Uge 2</td>
<td class="num">883,50 kr</td>
<td class="num">320,00 kr</td>
<td class="num">1.203,50 kr</td>
</tr>
<tr>
<td>Uge 3</td>
<td class="num">459,00 kr</td>
<td class="num">180,00 kr</td>
<td class="num">639,00 kr</td>
</tr>
<tr>
<td>Uge 4</td>
<td class="num">769,50 kr</td>
<td class="num">290,00 kr</td>
<td class="num">1.059,50 kr</td>
</tr>
<tr>
<td><b>I alt</b></td>
<td class="num"><b>2.685,00 kr</b></td>
<td class="num"><b>1.000,00 kr</b></td>
<td class="num"><b>3.685,00 kr</b></td>
</tr>
</tbody>
</table>
</div>
</section>
<section class="card">
<div class="hd">
<h2>Tillæg & fravær</h2>
</div>
<div class="bd">
<div class="grid" style="grid-template-columns: 1fr 1fr;">
<div>
<table>
<thead>
<tr>
<th>Tillæg</th>
<th class="num">Timer</th>
<th class="num">Beløb</th>
</tr>
</thead>
<tbody>
<tr>
<td>Aftentillæg (hverdage 1821)</td>
<td class="num">12,0</td>
<td class="num">336,00 kr</td>
</tr>
<tr>
<td>Lørdagstillæg (før kl. 14)</td>
<td class="num">16,0</td>
<td class="num">720,00 kr</td>
</tr>
<tr>
<td>Søndagstillæg</td>
<td class="num">0,0</td>
<td class="num">0,00 kr</td>
</tr>
<tr>
<td><b>Tillæg i alt</b></td>
<td class="num"></td>
<td class="num"><b>1.056,00 kr</b></td>
</tr>
</tbody>
</table>
</div>
<div>
<table>
<thead>
<tr>
<th>Fravær</th>
<th class="num">Dage</th>
<th class="num">Beløb</th>
</tr>
</thead>
<tbody>
<tr>
<td>Ferie med løn</td>
<td class="num">0</td>
<td class="num">0,00 kr</td>
</tr>
<tr>
<td>Sygdom</td>
<td class="num">0</td>
<td class="num">0,00 kr</td>
</tr>
<tr>
<td>Barns sygedag</td>
<td class="num">0</td>
<td class="num">0,00 kr</td>
</tr>
</tbody>
</table>
<p class="note">Ingen fravær registreret i perioden.</p>
</div>
</div>
</div>
</section>
<div class="ftr">
<div>Detaljer</div>
<div style="text-align:right">Lønspecifikation · Januar 2026</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,588 @@
<!DOCTYPE html>
<html lang="da">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Medarbejdere - Salon OS</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@phosphor-icons/web@2.1.2/src/regular/style.css" />
<link rel="stylesheet" href="css/konto.css">
<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;
}
/* Dark mode - system preference */
@media (prefers-color-scheme: dark) {
:root:not(.light-mode) {
--color-surface: #1e1e1e;
--color-background: #121212;
--color-background-hover: #2a2a2a;
--color-background-alt: #1a1a1a;
--color-border: #333;
--color-text: #e0e0e0;
--color-text-secondary: #999;
--color-teal: #26a69a;
--color-blue: #42a5f5;
--color-red: #ef5350;
--color-amber: #ffb74d;
--color-purple: #a78bfa;
--color-green: #66bb6a;
}
}
/* Manual dark mode override */
:root.dark-mode {
--color-surface: #1e1e1e;
--color-background: #121212;
--color-background-hover: #2a2a2a;
--color-background-alt: #1a1a1a;
--color-border: #333;
--color-text: #e0e0e0;
--color-text-secondary: #999;
--color-teal: #26a69a;
--color-blue: #42a5f5;
--color-red: #ef5350;
--color-amber: #ffb74d;
--color-purple: #a78bfa;
--color-green: #66bb6a;
}
/* ==========================================
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;
}
/* ==========================================
ROLE BADGES
========================================== */
swp-role-badge.leader {
background: color-mix(in srgb, var(--color-blue) 15%, transparent);
color: var(--color-blue);
}
/* ==========================================
STATS CARDS
========================================== */
swp-stats-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
margin-bottom: 24px;
}
swp-stat-card {
display: flex;
flex-direction: column;
gap: 4px;
padding: 20px;
background: var(--color-surface);
border-radius: 12px;
border: 1px solid var(--color-border);
}
swp-stat-value {
font-size: 28px;
font-weight: 600;
color: var(--color-text);
}
swp-stat-label {
font-size: 13px;
color: var(--color-text-secondary);
}
swp-stat-card.teal swp-stat-value {
color: var(--color-teal);
}
swp-stat-card.amber swp-stat-value {
color: var(--color-amber);
}
swp-stat-card.purple swp-stat-value {
color: var(--color-purple);
}
/* ==========================================
TABS
========================================== */
swp-tabs {
display: flex;
gap: 4px;
border-bottom: 1px solid var(--color-border);
margin-bottom: 24px;
}
swp-tab {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 20px;
font-size: 14px;
font-weight: 500;
color: var(--color-text-secondary);
cursor: pointer;
border-bottom: 2px solid transparent;
margin-bottom: -1px;
transition: all 150ms ease;
}
swp-tab:hover {
color: var(--color-text);
background: var(--color-background-hover);
}
swp-tab[data-active="true"] {
color: var(--color-teal);
border-bottom-color: var(--color-teal);
}
swp-tab i {
font-size: 18px;
}
swp-tab-content {
display: none;
}
swp-tab-content[data-active="true"] {
display: block;
}
/* ==========================================
PERMISSIONS MATRIX
========================================== */
swp-permissions-matrix {
display: block;
background: var(--color-surface);
border-radius: 12px;
overflow: hidden;
}
swp-permissions-matrix table {
width: 100%;
border-collapse: collapse;
}
swp-permissions-matrix th,
swp-permissions-matrix td {
padding: 14px 16px;
text-align: center;
border-bottom: 1px solid var(--color-border);
}
swp-permissions-matrix th:first-child,
swp-permissions-matrix td:first-child {
text-align: left;
font-weight: 500;
}
swp-permissions-matrix thead th {
background: var(--color-background-alt);
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--color-text-secondary);
}
swp-permissions-matrix tbody tr:last-child td {
border-bottom: none;
}
swp-permissions-matrix .permission-name {
display: flex;
align-items: center;
gap: 10px;
}
swp-permissions-matrix .permission-name i {
font-size: 18px;
color: var(--color-text-secondary);
}
swp-permissions-matrix .check {
color: var(--color-teal);
font-size: 20px;
}
swp-permissions-matrix .no-access {
color: var(--color-border);
font-size: 16px;
}
</style>
</head>
<body>
<swp-page-container>
<!-- Page Header -->
<swp-page-header>
<swp-page-title>
<h1>Medarbejdere</h1>
<p>Administrer brugere, roller og rettigheder</p>
</swp-page-title>
</swp-page-header>
<!-- Stats Cards -->
<swp-stats-row>
<swp-stat-card class="teal">
<swp-stat-value>4</swp-stat-value>
<swp-stat-label>Aktive medarbejdere</swp-stat-label>
</swp-stat-card>
<swp-stat-card class="amber">
<swp-stat-value>1</swp-stat-value>
<swp-stat-label>Afventer invitation</swp-stat-label>
</swp-stat-card>
<swp-stat-card class="purple">
<swp-stat-value>4</swp-stat-value>
<swp-stat-label>Roller defineret</swp-stat-label>
</swp-stat-card>
</swp-stats-row>
<!-- Tabs -->
<swp-tabs>
<swp-tab data-tab="brugere" data-active="true">
<i class="ph ph-users"></i>
Brugere
</swp-tab>
<swp-tab data-tab="roller">
<i class="ph ph-shield-check"></i>
Roller
</swp-tab>
</swp-tabs>
<!-- Tab: Brugere -->
<swp-tab-content data-tab="brugere" data-active="true">
<swp-users-header>
<swp-users-count>
<strong>5 af 8</strong> brugere
<swp-users-progress>
<swp-users-progress-bar style="width: 62.5%"></swp-users-progress-bar>
</swp-users-progress>
</swp-users-count>
<swp-btn class="primary">
<i class="ph ph-user-plus"></i>
Inviter bruger
</swp-btn>
</swp-users-header>
<swp-table-card>
<swp-table>
<swp-table-header>
<swp-table-row>
<swp-table-cell>Bruger</swp-table-cell>
<swp-table-cell>Rolle</swp-table-cell>
<swp-table-cell>Status</swp-table-cell>
<swp-table-cell>Sidst aktiv</swp-table-cell>
<swp-table-cell></swp-table-cell>
</swp-table-row>
</swp-table-header>
<swp-table-body>
<!-- User 1 - Owner -->
<swp-table-row>
<swp-table-cell>
<swp-user-info>
<swp-user-avatar>MJ</swp-user-avatar>
<swp-user-details>
<swp-user-name>Maria Jensen</swp-user-name>
<swp-user-email>maria@salonbeauty.dk</swp-user-email>
</swp-user-details>
</swp-user-info>
</swp-table-cell>
<swp-table-cell>
<swp-role-badge class="owner">Ejer</swp-role-badge>
</swp-table-cell>
<swp-table-cell>
<swp-status-badge class="active">
<swp-status-dot></swp-status-dot>
Aktiv
</swp-status-badge>
</swp-table-cell>
<swp-table-cell>I dag, 14:32</swp-table-cell>
<swp-table-cell>
<swp-table-actions>
<swp-icon-btn title="Rediger">
<i class="ph ph-pencil"></i>
</swp-icon-btn>
</swp-table-actions>
</swp-table-cell>
</swp-table-row>
<!-- User 2 - Admin -->
<swp-table-row>
<swp-table-cell>
<swp-user-info>
<swp-user-avatar class="purple">AS</swp-user-avatar>
<swp-user-details>
<swp-user-name>Anna Sørensen</swp-user-name>
<swp-user-email>anna@salonbeauty.dk</swp-user-email>
</swp-user-details>
</swp-user-info>
</swp-table-cell>
<swp-table-cell>
<swp-role-badge class="admin">Admin</swp-role-badge>
</swp-table-cell>
<swp-table-cell>
<swp-status-badge class="active">
<swp-status-dot></swp-status-dot>
Aktiv
</swp-status-badge>
</swp-table-cell>
<swp-table-cell>I dag, 12:15</swp-table-cell>
<swp-table-cell>
<swp-table-actions>
<swp-icon-btn title="Rediger">
<i class="ph ph-pencil"></i>
</swp-icon-btn>
<swp-icon-btn class="danger" title="Fjern bruger">
<i class="ph ph-trash"></i>
</swp-icon-btn>
</swp-table-actions>
</swp-table-cell>
</swp-table-row>
<!-- User 3 - Leder -->
<swp-table-row>
<swp-table-cell>
<swp-user-info>
<swp-user-avatar class="blue">LP</swp-user-avatar>
<swp-user-details>
<swp-user-name>Louise Pedersen</swp-user-name>
<swp-user-email>louise@salonbeauty.dk</swp-user-email>
</swp-user-details>
</swp-user-info>
</swp-table-cell>
<swp-table-cell>
<swp-role-badge class="leader">Leder</swp-role-badge>
</swp-table-cell>
<swp-table-cell>
<swp-status-badge class="active">
<swp-status-dot></swp-status-dot>
Aktiv
</swp-status-badge>
</swp-table-cell>
<swp-table-cell>I går, 17:45</swp-table-cell>
<swp-table-cell>
<swp-table-actions>
<swp-icon-btn title="Rediger">
<i class="ph ph-pencil"></i>
</swp-icon-btn>
<swp-icon-btn class="danger" title="Fjern bruger">
<i class="ph ph-trash"></i>
</swp-icon-btn>
</swp-table-actions>
</swp-table-cell>
</swp-table-row>
<!-- User 4 -->
<swp-table-row>
<swp-table-cell>
<swp-user-info>
<swp-user-avatar class="amber">KN</swp-user-avatar>
<swp-user-details>
<swp-user-name>Katrine Nielsen</swp-user-name>
<swp-user-email>katrine@salonbeauty.dk</swp-user-email>
</swp-user-details>
</swp-user-info>
</swp-table-cell>
<swp-table-cell>
<swp-role-badge>Medarbejder</swp-role-badge>
</swp-table-cell>
<swp-table-cell>
<swp-status-badge class="active">
<swp-status-dot></swp-status-dot>
Aktiv
</swp-status-badge>
</swp-table-cell>
<swp-table-cell>27. dec, 09:30</swp-table-cell>
<swp-table-cell>
<swp-table-actions>
<swp-icon-btn title="Rediger">
<i class="ph ph-pencil"></i>
</swp-icon-btn>
<swp-icon-btn class="danger" title="Fjern bruger">
<i class="ph ph-trash"></i>
</swp-icon-btn>
</swp-table-actions>
</swp-table-cell>
</swp-table-row>
<!-- User 5 - Invited -->
<swp-table-row>
<swp-table-cell>
<swp-user-info>
<swp-user-avatar class="purple">SH</swp-user-avatar>
<swp-user-details>
<swp-user-name>Sofie Hansen</swp-user-name>
<swp-user-email>sofie@salonbeauty.dk</swp-user-email>
</swp-user-details>
</swp-user-info>
</swp-table-cell>
<swp-table-cell>
<swp-role-badge>Medarbejder</swp-role-badge>
</swp-table-cell>
<swp-table-cell>
<swp-status-badge class="invited">
<swp-status-dot></swp-status-dot>
Invitation sendt
</swp-status-badge>
</swp-table-cell>
<swp-table-cell>-</swp-table-cell>
<swp-table-cell>
<swp-table-actions>
<swp-icon-btn title="Send invitation igen">
<i class="ph ph-paper-plane-tilt"></i>
</swp-icon-btn>
<swp-icon-btn class="danger" title="Annuller invitation">
<i class="ph ph-x"></i>
</swp-icon-btn>
</swp-table-actions>
</swp-table-cell>
</swp-table-row>
</swp-table-body>
</swp-table>
</swp-table-card>
</swp-tab-content>
<!-- Tab: Roller -->
<swp-tab-content data-tab="roller">
<swp-permissions-matrix>
<table>
<thead>
<tr>
<th>Rettighed</th>
<th>Ejer</th>
<th>Admin</th>
<th>Leder</th>
<th>Medarbejder</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span class="permission-name">
<i class="ph ph-calendar"></i>
Kalender
</span>
</td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-check-circle check"></i></td>
</tr>
<tr>
<td>
<span class="permission-name">
<i class="ph ph-users"></i>
Medarbejdere
</span>
</td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-minus no-access"></i></td>
</tr>
<tr>
<td>
<span class="permission-name">
<i class="ph ph-address-book"></i>
Kunder
</span>
</td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-check-circle check"></i></td>
</tr>
<tr>
<td>
<span class="permission-name">
<i class="ph ph-chart-bar"></i>
Rapporter & Økonomi
</span>
</td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-check-circle check"></i></td>
<td><i class="ph ph-minus no-access"></i></td>
<td><i class="ph ph-minus no-access"></i></td>
</tr>
</tbody>
</table>
</swp-permissions-matrix>
</swp-tab-content>
</swp-page-container>
<script>
// Simple tab switching
document.querySelectorAll('swp-tab').forEach(tab => {
tab.addEventListener('click', () => {
const tabName = tab.dataset.tab;
// Update tab active states
document.querySelectorAll('swp-tab').forEach(t => t.removeAttribute('data-active'));
tab.setAttribute('data-active', 'true');
// Update content active states
document.querySelectorAll('swp-tab-content').forEach(c => c.removeAttribute('data-active'));
document.querySelector(`swp-tab-content[data-tab="${tabName}"]`).setAttribute('data-active', 'true');
});
});
</script>
</body>
</html>

1133
wwwroot/poc-salg.html Normal file

File diff suppressed because it is too large Load diff