Moving away from Azure Devops #1

Merged
Janus007 merged 113 commits from refac into master 2026-02-03 00:04:27 +01:00
Showing only changes of commit b408b83cac - Show all commits

View file

@ -652,6 +652,10 @@
background: var(--color-text-secondary);
}
.tab-indicator.purple {
background: #8b5cf6;
}
/* Tab Content Container */
swp-journal-tab-content {
display: none;
@ -752,6 +756,11 @@
background: color-mix(in srgb, var(--color-teal) 15%, var(--b-mix));
}
swp-journal-entry-type.analyse {
color: #7c3aed;
background: color-mix(in srgb, #8b5cf6 15%, var(--b-mix));
}
swp-journal-entry-date {
font-size: 12px;
color: var(--color-text-secondary);
@ -1940,6 +1949,111 @@
outline: none;
border-color: var(--color-teal);
}
/* ==========================================
ANALYSE PANEL (extends add-note styles)
========================================== */
swp-analyse-panel {
position: fixed;
top: 0;
right: 340px;
bottom: 0;
width: 440px;
background: var(--color-surface);
border-left: 1px solid var(--color-border);
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
transform: translateX(0);
visibility: hidden;
transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1),
visibility 0ms 250ms;
display: flex;
flex-direction: column;
z-index: 980;
}
swp-analyse-panel.open {
transform: translateX(-100%);
visibility: visible;
transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1),
visibility 0ms 0ms;
}
swp-analyse-panel input[type="text"] {
padding: 10px 12px;
font-size: 13px;
border: 1px solid var(--color-border);
border-radius: 6px;
background: var(--color-surface);
}
swp-analyse-panel input[type="text"]:focus {
outline: none;
border-color: #8b5cf6;
}
swp-analyse-panel select {
padding: 10px 12px;
font-size: 13px;
border: 1px solid var(--color-border);
border-radius: 6px;
background: var(--color-surface);
cursor: pointer;
}
swp-analyse-panel select:focus {
outline: none;
border-color: #8b5cf6;
}
swp-analyse-panel textarea {
width: 100%;
min-height: 80px;
padding: 12px;
font-family: inherit;
font-size: 13px;
border: 1px solid var(--color-border);
border-radius: 6px;
background: var(--color-surface);
resize: vertical;
line-height: 1.5;
}
swp-analyse-panel textarea:focus {
outline: none;
border-color: #8b5cf6;
}
/* Analyse tags */
swp-add-note-tag-option[data-tag="analyse"].selected {
background: color-mix(in srgb, #8b5cf6 15%, var(--b-mix));
border-color: #8b5cf6;
color: #7c3aed;
}
swp-add-note-tag-option[data-tag="hovedbund"].selected {
background: color-mix(in srgb, var(--b-color-amber) 15%, var(--b-mix));
border-color: var(--b-color-amber);
color: #b45309;
}
swp-add-note-tag-option[data-tag="analyse"].selected::before {
background: #8b5cf6;
border-color: #8b5cf6;
}
swp-add-note-tag-option[data-tag="hovedbund"].selected::before {
background: var(--b-color-amber);
border-color: var(--b-color-amber);
}
/* Journal tag for analyse */
swp-journal-tag.tag-analyse {
background: color-mix(in srgb, #8b5cf6 15%, var(--b-mix));
border-color: #8b5cf6;
color: #7c3aed;
}
swp-journal-tag.tag-hovedbund {
background: color-mix(in srgb, var(--b-color-amber) 15%, var(--b-mix));
border-color: var(--b-color-amber);
color: #b45309;
}
</style>
</head>
<body>
@ -1998,7 +2112,7 @@
<swp-journal-tabs>
<swp-journal-tab class="active" data-tab="noter" onclick="switchJournalTab('noter')"><span class="tab-indicator blue"></span>Noter</swp-journal-tab>
<swp-journal-tab data-tab="farveformler" onclick="switchJournalTab('farveformler')"><span class="tab-indicator amber"></span>Farveformler</swp-journal-tab>
<swp-journal-tab class="disabled"><span class="tab-indicator gray"></span>Analyse</swp-journal-tab>
<swp-journal-tab data-tab="analyse" onclick="switchJournalTab('analyse')"><span class="tab-indicator purple"></span>Analyse</swp-journal-tab>
</swp-journal-tabs>
<!-- Tab: Noter -->
@ -2132,6 +2246,66 @@
</swp-journal-content>
</swp-journal-tab-content>
<!-- Tab: Analyse -->
<swp-journal-tab-content id="tabAnalyse">
<swp-journal-tab-header>
<swp-journal-tab-title>Hår & hovedbund <span>(analyse)</span></swp-journal-tab-title>
<swp-journal-tab-desc>Struktureret analyse af hår og hovedbund. Kan blive til advarsel.</swp-journal-tab-desc>
<swp-journal-add-btn onclick="openAnalyse()">+ Tilføj analyse</swp-journal-add-btn>
</swp-journal-tab-header>
<swp-journal-content>
<!-- Preview Entry for Analyse -->
<swp-journal-entry id="previewEntryAnalyse" class="preview hidden">
<swp-journal-entry-meta>
<swp-journal-entry-type class="analyse">Analyse</swp-journal-entry-type>
<swp-journal-entry-tags id="previewTagsAnalyse"></swp-journal-entry-tags>
</swp-journal-entry-meta>
<swp-journal-entry-text id="previewTextAnalyse">(Udfyld felter...)</swp-journal-entry-text>
<swp-journal-entry-footer>
<swp-journal-entry-date>I dag</swp-journal-entry-date>
<swp-journal-entry-icons>
<swp-journal-entry-visibility>
<img src="icons/eye.svg" class="entry-icon" alt="">
<span>Alle</span>
</swp-journal-entry-visibility>
</swp-journal-entry-icons>
</swp-journal-entry-footer>
</swp-journal-entry>
<swp-journal-entry>
<swp-journal-entry-meta>
<swp-journal-entry-type class="analyse">Analyse</swp-journal-entry-type>
<swp-journal-entry-tags>
<swp-journal-tag class="tag-analyse">Hovedbund</swp-journal-tag>
<swp-journal-tag class="tag-sensitiv">Sensitiv</swp-journal-tag>
</swp-journal-entry-tags>
<swp-journal-entry-delete title="Slet">🗑</swp-journal-entry-delete>
</swp-journal-entry-meta>
<swp-journal-entry-text>
• Hovedbund: Let irriteret<br>
• Hår: <span class="mono">Medium · Bølget</span><br>
• Porøsitet: <span class="mono">Medium</span><br>
• Kemisk beh.: Nej<br><br>
Let rødme ved hårgrænsen. Anbefalet parfumefri shampoo.
</swp-journal-entry-text>
<swp-journal-entry-footer>
<swp-journal-entry-date>2. sep 2025 · Af: Nina</swp-journal-entry-date>
<swp-journal-entry-icons>
<swp-journal-entry-visibility>
<img src="icons/eye.svg" class="entry-icon" alt="">
<span>Alle</span>
</swp-journal-entry-visibility>
<swp-journal-entry-marking class="warning">
<img src="icons/warning.svg" class="entry-icon" alt="">
<span>Advarsel</span>
</swp-journal-entry-marking>
</swp-journal-entry-icons>
</swp-journal-entry-footer>
</swp-journal-entry>
</swp-journal-content>
</swp-journal-tab-content>
<!-- Kundeprofil Toggle -->
<swp-journal-profile-section>
<swp-journal-profile-toggle onclick="toggleJournalProfile()">
@ -2294,6 +2468,130 @@
</swp-add-note-footer>
</swp-farveformel-panel>
<!-- Analyse Panel -->
<swp-analyse-panel id="analysePanel">
<swp-add-note-header>
<swp-add-note-title>Shampoo & hovedbund-analyse</swp-add-note-title>
<swp-add-note-close onclick="closeAnalyse()"></swp-add-note-close>
</swp-add-note-header>
<swp-add-note-content>
<swp-add-note-desc>Hurtige valg + bemærkning. Kan blive til "sticky warning".</swp-add-note-desc>
<!-- Row 1: Hovedbund + Irritation -->
<swp-add-note-row>
<swp-add-note-field>
<swp-add-note-label>Hovedbund (tilstand)</swp-add-note-label>
<select id="anHovedbund">
<option value="">Vælg...</option>
<option value="Normal">Normal</option>
<option value="Tør">Tør</option>
<option value="Fedtet">Fedtet</option>
<option value="Let irriteret">Let irriteret</option>
<option value="Irriteret">Irriteret</option>
</select>
</swp-add-note-field>
<swp-add-note-field>
<swp-add-note-label>Irritation</swp-add-note-label>
<select id="anIrritation">
<option value="">Vælg...</option>
<option value="Ingen">Ingen</option>
<option value="Let">Let</option>
<option value="Moderat">Moderat</option>
<option value="Kraftig">Kraftig</option>
</select>
</swp-add-note-field>
</swp-add-note-row>
<!-- Row 2: Hår tykkelse + struktur -->
<swp-add-note-row>
<swp-add-note-field>
<swp-add-note-label>Hår (tykkelse)</swp-add-note-label>
<select id="anHaarTykkelse">
<option value="">Vælg...</option>
<option value="Fint">Fint</option>
<option value="Medium">Medium</option>
<option value="Tykt">Tykt</option>
</select>
</swp-add-note-field>
<swp-add-note-field>
<swp-add-note-label>Hår (struktur)</swp-add-note-label>
<select id="anHaarStruktur">
<option value="">Vælg...</option>
<option value="Glat">Glat</option>
<option value="Bølget">Bølget</option>
<option value="Krøllet">Krøllet</option>
</select>
</swp-add-note-field>
</swp-add-note-row>
<!-- Row 3: Porøsitet + Kemisk behandling -->
<swp-add-note-row>
<swp-add-note-field>
<swp-add-note-label>Porøsitet</swp-add-note-label>
<select id="anPorositet">
<option value="">Vælg...</option>
<option value="Lav">Lav</option>
<option value="Medium">Medium</option>
<option value="Høj">Høj</option>
</select>
</swp-add-note-field>
<swp-add-note-field>
<swp-add-note-label>Tidligere kemisk behandling?</swp-add-note-label>
<select id="anKemisk">
<option value="">Vælg...</option>
<option value="Nej">Nej</option>
<option value="Ja">Ja</option>
</select>
</swp-add-note-field>
</swp-add-note-row>
<!-- Row 4: Shampoo + Hjemmepleje -->
<swp-add-note-row>
<swp-add-note-field>
<swp-add-note-label>Anvendt shampoo</swp-add-note-label>
<input type="text" id="anShampoo" placeholder="Fx: Kerastase Bain">
</swp-add-note-field>
<swp-add-note-field>
<swp-add-note-label>Anbefalet hjemmepleje</swp-add-note-label>
<input type="text" id="anHjemmepleje" placeholder="Fx: Parfumefri shampoo">
</swp-add-note-field>
</swp-add-note-row>
<!-- Bemærkning -->
<swp-add-note-field class="full-width">
<swp-add-note-label>Bemærkning</swp-add-note-label>
<textarea id="anBemaerkning" placeholder="Fx: Let rødme ved hårgrænsen. Undgå parfume og stærke sulfater."></textarea>
</swp-add-note-field>
<!-- Row 5: Advarsel + Tags -->
<swp-add-note-row>
<swp-add-note-field>
<swp-add-note-label>Gør til advarsel på kundekort?</swp-add-note-label>
<select id="anAdvarsel">
<option value="Nej">Nej</option>
<option value="Ja">Ja</option>
</select>
<swp-add-note-help>Brug "Ja" ved fx allergi/sensitivitet.</swp-add-note-help>
</swp-add-note-field>
<swp-add-note-field>
<swp-add-note-label>Tags</swp-add-note-label>
<swp-add-note-tags>
<swp-add-note-tag-option class="selected" data-tag="analyse">Analyse</swp-add-note-tag-option>
<swp-add-note-tag-option data-tag="hovedbund">Hovedbund</swp-add-note-tag-option>
<swp-add-note-tag-option data-tag="sensitiv">Sensitiv</swp-add-note-tag-option>
<swp-add-note-tag-option data-tag="allergi">Allergi</swp-add-note-tag-option>
</swp-add-note-tags>
</swp-add-note-field>
</swp-add-note-row>
</swp-add-note-content>
<swp-add-note-footer>
<swp-add-note-btn class="secondary" onclick="closeAnalyse()">Annuller</swp-add-note-btn>
<swp-add-note-btn class="primary" onclick="saveAnalyse()">Gem analyse</swp-add-note-btn>
</swp-add-note-footer>
</swp-analyse-panel>
<!-- Customer Details Panel -->
<swp-customer-panel id="customerPanel">
<swp-customer-panel-header>
@ -2642,6 +2940,7 @@
document.getElementById('journalLink').classList.remove('panel-open');
closeAddNote();
closeFarveformel();
closeAnalyse();
}
function switchJournalTab(tabName) {
@ -2652,9 +2951,11 @@
// Update tab content
document.getElementById('tabNoter').classList.toggle('active', tabName === 'noter');
document.getElementById('tabFarveformler').classList.toggle('active', tabName === 'farveformler');
document.getElementById('tabAnalyse').classList.toggle('active', tabName === 'analyse');
// Close any open panels
closeAddNote();
closeFarveformel();
closeAnalyse();
}
function openAddNote() {
@ -2958,6 +3259,145 @@
originalCloseAddNote();
activePanel = null;
};
// ==========================================
// ANALYSE PANEL
// ==========================================
// Analyse form elements
const anHovedbund = document.getElementById('anHovedbund');
const anIrritation = document.getElementById('anIrritation');
const anHaarTykkelse = document.getElementById('anHaarTykkelse');
const anHaarStruktur = document.getElementById('anHaarStruktur');
const anPorositet = document.getElementById('anPorositet');
const anKemisk = document.getElementById('anKemisk');
const anShampoo = document.getElementById('anShampoo');
const anHjemmepleje = document.getElementById('anHjemmepleje');
const anBemaerkning = document.getElementById('anBemaerkning');
const anAdvarsel = document.getElementById('anAdvarsel');
// Analyse preview elements
const previewEntryAnalyse = document.getElementById('previewEntryAnalyse');
const previewTextAnalyse = document.getElementById('previewTextAnalyse');
const previewTagsAnalyse = document.getElementById('previewTagsAnalyse');
function openAnalyse() {
document.getElementById('analysePanel').classList.add('open');
activePanel = 'analyse';
showAnalysePreview();
}
function closeAnalyse() {
document.getElementById('analysePanel').classList.remove('open');
hideAnalysePreview();
resetAnalyseForm();
activePanel = null;
}
function showAnalysePreview() {
previewEntryAnalyse.classList.remove('hidden');
updateAnalysePreview();
updateAnalysePreviewTags();
}
function hideAnalysePreview() {
previewEntryAnalyse.classList.add('hidden');
}
function updateAnalysePreview() {
const lines = [];
if (anHovedbund.value) {
lines.push(`• Hovedbund: ${anHovedbund.value}`);
}
if (anIrritation.value) {
lines.push(`• Irritation: ${anIrritation.value}`);
}
if (anHaarTykkelse.value || anHaarStruktur.value) {
const haarParts = [];
if (anHaarTykkelse.value) haarParts.push(anHaarTykkelse.value);
if (anHaarStruktur.value) haarParts.push(anHaarStruktur.value);
lines.push(`• Hår: <span class="mono">${haarParts.join(' · ')}</span>`);
}
if (anPorositet.value) {
lines.push(`• Porøsitet: <span class="mono">${anPorositet.value}</span>`);
}
if (anKemisk.value) {
lines.push(`• Kemisk beh.: ${anKemisk.value}`);
}
if (anShampoo.value) {
lines.push(`• Shampoo: ${anShampoo.value}`);
}
if (anHjemmepleje.value) {
lines.push(`• Hjemmepleje: ${anHjemmepleje.value}`);
}
if (anBemaerkning.value) {
lines.push(`<br>${anBemaerkning.value}`);
}
previewTextAnalyse.innerHTML = lines.length > 0 ? lines.join('<br>') : '(Udfyld felter...)';
}
function updateAnalysePreviewTags() {
const analysePanelTags = document.querySelectorAll('#analysePanel swp-add-note-tag-option.selected');
previewTagsAnalyse.innerHTML = '';
analysePanelTags.forEach(tag => {
const tagEl = document.createElement('swp-journal-tag');
tagEl.textContent = tag.textContent;
tagEl.classList.add('tag-' + tag.dataset.tag);
previewTagsAnalyse.appendChild(tagEl);
});
}
function resetAnalyseForm() {
anHovedbund.value = '';
anIrritation.value = '';
anHaarTykkelse.value = '';
anHaarStruktur.value = '';
anPorositet.value = '';
anKemisk.value = '';
anShampoo.value = '';
anHjemmepleje.value = '';
anBemaerkning.value = '';
anAdvarsel.value = 'Nej';
// Reset tags - only "Analyse" selected by default
document.querySelectorAll('#analysePanel swp-add-note-tag-option').forEach(tag => {
if (tag.dataset.tag === 'analyse') {
tag.classList.add('selected');
} else {
tag.classList.remove('selected');
}
});
}
function saveAnalyse() {
// In a real app, this would save to backend
alert('Analyse gemt!');
closeAnalyse();
}
// Add event listeners for analyse form fields
[anHovedbund, anIrritation, anHaarTykkelse, anHaarStruktur, anPorositet, anKemisk, anShampoo, anHjemmepleje, anBemaerkning, anAdvarsel].forEach(el => {
el.addEventListener('input', () => {
if (activePanel === 'analyse') {
updateAnalysePreview();
}
});
el.addEventListener('change', () => {
if (activePanel === 'analyse') {
updateAnalysePreview();
}
});
});
// Add tag toggle listeners for analyse panel
document.querySelectorAll('#analysePanel swp-add-note-tag-option').forEach(tag => {
tag.onclick = () => {
tag.classList.toggle('selected');
updateAnalysePreviewTags();
};
});
</script>
<!-- Chart initialization -->