Files
boc/landvex-site/landvex-inspector.html
T
Bernt 6989a98d75 feat: Passwordless cross-device authentication
- Arkitektur: docs/auth/passwordless-architecture.md
- Backend: iom/quixzoom-auth-service/ (FastAPI + Redis)
- Webb: quixzoom-market-pages/se/login/ (QR-kod + polling)
- App: iom/quixzoom-app/src/features/auth/ (push + deep links)

Flöde: QR-kod → app-godkännande → webb-inloggad
2026-07-07 07:11:50 +00:00

900 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="sv">
<head>
<meta charset="UTF-8">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<meta name="color-scheme" content="light dark">
<title>LandveX — Inspektörsportal</title>
<link rel="stylesheet" >
<style>
/*
LANDVEX INSPEKTÖRSPORTAL — iOS Native
*/
* { box-sizing: border-box; margin: 0; padding: 0; -webkit-font-smoothing: antialiased; }
body {
font-family: var(--font-text);
background: var(--grouped-background-primary);
color: var(--label-primary);
min-height: 100vh;
padding-bottom: calc(60px + env(safe-area-inset-bottom));
}
/* NAV */
.nav-bar {
position: sticky;
top: 0;
z-index: 100;
background: var(--glass-bg);
backdrop-filter: var(--glass-blur);
-webkit-backdrop-filter: var(--glass-blur);
border-bottom: 0.5px solid var(--separator);
padding: 0 16px;
}
.nav-top {
height: 44px;
display: flex;
align-items: center;
justify-content: space-between;
}
.nav-brand {
display: flex;
align-items: center;
gap: 8px;
}
.brand-icon {
width: 28px;
height: 28px;
background: linear-gradient(135deg, #0055CC, #007AFF);
border-radius: var(--radius-sm);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 12px;
font-weight: 800;
}
.brand-label {
font-size: 17px;
font-weight: 600;
letter-spacing: -0.4px;
}
.badge-inspector {
font-size: 10px;
font-weight: 700;
padding: 3px 7px;
background: rgba(88,86,214,0.15);
color: var(--ios-indigo);
border-radius: var(--radius-xl);
letter-spacing: 0.3px;
}
/* DATE HEADER */
.date-header {
padding: 16px 16px 4px;
font-size: 13px;
font-weight: 600;
color: var(--label-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
}
.day-title {
font-family: var(--font-display);
font-size: 28px;
font-weight: 700;
letter-spacing: -0.5px;
padding: 2px 16px 16px;
}
/* MISSION CARD */
.mission-card {
margin: 0 16px 12px;
background: var(--grouped-background-secondary);
border-radius: var(--radius-lg);
border: 0.5px solid var(--separator);
overflow: hidden;
}
.mission-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 16px;
border-bottom: 0.5px solid var(--separator);
cursor: pointer;
transition: background 0.15s;
}
.mission-header:active { background: var(--fill-quaternary); }
.mission-title {
font-size: 17px;
font-weight: 600;
letter-spacing: -0.3px;
}
.mission-sub {
font-size: 13px;
color: var(--label-secondary);
margin-top: 2px;
}
.mission-number {
width: 44px;
height: 44px;
border-radius: var(--radius-full);
background: linear-gradient(135deg, #007AFF, #0055CC);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 20px;
font-weight: 700;
flex-shrink: 0;
}
.mission-body {
padding: 0 16px;
}
.mission-row {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 0;
border-bottom: 0.5px solid var(--separator);
font-size: 15px;
}
.mission-row:last-child { border-bottom: none; }
.mission-row-icon {
font-size: 18px;
width: 24px;
text-align: center;
flex-shrink: 0;
}
.mission-row-label { flex: 1; }
.mission-row-value {
font-size: 15px;
color: var(--label-secondary);
font-weight: 500;
}
.mission-actions {
padding: 14px 16px;
display: flex;
gap: 10px;
border-top: 0.5px solid var(--separator);
}
.btn-start {
flex: 2;
height: 44px;
background: var(--ios-green);
color: white;
border: none;
border-radius: var(--radius-md);
font-size: 15px;
font-weight: 600;
font-family: var(--font-text);
cursor: pointer;
transition: opacity 0.15s;
}
.btn-start:active { opacity: 0.8; }
.btn-nav {
flex: 1;
height: 44px;
background: var(--fill-secondary);
color: var(--ios-blue);
border: none;
border-radius: var(--radius-md);
font-size: 15px;
font-weight: 600;
font-family: var(--font-text);
cursor: pointer;
}
/* FORM SECTIONS */
.form-section {
margin: 24px 16px 0;
}
.section-title {
font-size: 20px;
font-weight: 700;
letter-spacing: -0.4px;
margin-bottom: 10px;
}
.form-card {
background: var(--grouped-background-secondary);
border-radius: var(--radius-lg);
border: 0.5px solid var(--separator);
overflow: hidden;
}
.form-row {
display: flex;
align-items: center;
padding: 12px 16px;
border-bottom: 0.5px solid var(--separator);
gap: 12px;
}
.form-row:last-child { border-bottom: none; }
.form-row-label {
font-size: 15px;
font-weight: 500;
flex: 1;
}
.form-row-input {
text-align: right;
flex: 1;
background: none;
border: none;
outline: none;
font-size: 15px;
font-family: var(--font-text);
color: var(--label-secondary);
min-width: 0;
}
.form-row-input::placeholder { color: var(--label-quaternary); }
.form-row-select {
flex: 1;
text-align: right;
background: none;
border: none;
outline: none;
font-size: 15px;
font-family: var(--font-text);
color: var(--label-secondary);
cursor: pointer;
appearance: none;
}
.form-textarea-wrap {
padding: 12px 16px;
}
.form-textarea {
width: 100%;
min-height: 100px;
background: none;
border: none;
outline: none;
font-size: 15px;
font-family: var(--font-text);
color: var(--label-primary);
resize: vertical;
line-height: 1.5;
}
.form-textarea::placeholder { color: var(--label-quaternary); }
/* CHECKLIST */
.checklist-item {
display: flex;
align-items: center;
padding: 12px 16px;
border-bottom: 0.5px solid var(--separator);
gap: 12px;
cursor: pointer;
transition: background 0.15s;
}
.checklist-item:last-child { border-bottom: none; }
.checklist-item:active { background: var(--fill-quaternary); }
.check-box {
width: 24px;
height: 24px;
border-radius: var(--radius-full);
border: 2px solid var(--ios-blue);
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
}
.check-box.checked {
background: var(--ios-blue);
border-color: var(--ios-blue);
}
.check-mark {
color: white;
font-size: 12px;
font-weight: 700;
opacity: 0;
transition: opacity 0.2s;
}
.check-box.checked .check-mark { opacity: 1; }
.checklist-text { flex: 1; font-size: 15px; }
.checklist-text.checked { color: var(--label-secondary); text-decoration: line-through; }
/* PHOTO UPLOAD */
.photo-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 3px;
padding: 12px 16px;
}
.photo-thumb {
aspect-ratio: 1;
border-radius: var(--radius-md);
overflow: hidden;
background: var(--fill-secondary);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
position: relative;
transition: opacity 0.15s;
}
.photo-thumb:active { opacity: 0.7; }
.photo-thumb.add-photo {
border: 2px dashed var(--separator);
background: transparent;
flex-direction: column;
gap: 4px;
}
.photo-thumb.add-photo .add-icon {
font-size: 28px;
color: var(--ios-blue);
}
.photo-thumb.add-photo .add-label {
font-size: 11px;
color: var(--ios-blue);
font-weight: 500;
}
.photo-placeholder {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 32px;
background: var(--fill-secondary);
}
/* SUBMIT AREA */
.submit-area {
padding: 20px 16px 32px;
}
.submit-btn {
width: 100%;
height: 54px;
background: linear-gradient(135deg, #007AFF, #0055CC);
color: white;
border: none;
border-radius: var(--radius-lg);
font-size: 17px;
font-weight: 700;
font-family: var(--font-display);
cursor: pointer;
letter-spacing: -0.3px;
transition: opacity 0.15s, transform 0.1s;
box-shadow: 0 4px 20px rgba(0,122,255,0.35);
}
.submit-btn:active {
opacity: 0.85;
transform: scale(0.98);
}
.submit-note {
text-align: center;
font-size: 12px;
color: var(--label-tertiary);
margin-top: 10px;
}
/* PROGRESS BAR */
.progress-wrap {
padding: 0 16px 16px;
}
.progress-header {
display: flex;
justify-content: space-between;
font-size: 13px;
color: var(--label-secondary);
margin-bottom: 6px;
}
.progress-track {
height: 4px;
background: var(--fill-tertiary);
border-radius: var(--radius-sm);
overflow: hidden;
}
.progress-fill {
height: 100%;
border-radius: var(--radius-sm);
background: var(--ios-blue);
transition: width 0.4s;
}
/* TAB BAR */
.tab-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: calc(49px + env(safe-area-inset-bottom));
padding-bottom: env(safe-area-inset-bottom);
background: var(--glass-bg);
backdrop-filter: var(--glass-blur);
-webkit-backdrop-filter: var(--glass-blur);
border-top: 0.5px solid var(--separator);
display: flex;
align-items: flex-start;
justify-content: space-around;
padding-top: 8px;
z-index: 90;
}
.tab-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
cursor: pointer;
flex: 1;
opacity: 0.55;
transition: opacity 0.15s;
}
.tab-item.active { opacity: 1; }
.tab-icon { font-size: 22px; }
.tab-label { font-size: 10px; font-weight: 500; color: var(--label-secondary); }
.tab-item.active .tab-label { color: var(--ios-blue); }
/* NOTIFICATION DOT */
.notif-dot {
position: relative;
}
.notif-dot::after {
content: '3';
position: absolute;
top: -4px;
right: -8px;
background: var(--ios-red);
color: white;
font-size: 9px;
font-weight: 700;
width: 16px;
height: 16px;
border-radius: var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
border: 2px solid var(--grouped-background-primary);
}
@media (max-width: 640px) {
.hero h1 { font-size: 2rem !important; }
.hero p { font-size: 1rem !important; }
.card { padding: 1.5rem !important; }
.grid { grid-template-columns: 1fr !important; }
.btn { padding: 0.75rem 1.5rem !important; font-size: 1rem !important; }
}
</style>
<style id="wcag-contrast-enforcement">
/* AAMOS GLOBAL CONTRAST ENFORCEMENT — WCAG AA (4.5:1 minimum) */
/* Regel: Ingen text under 70% opacity. Aldrig. */
body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
/* Fix common low-contrast patterns */
[style*="rgba(60,60,67,0.4)"] { color: rgba(60,60,67,0.65) !important; }
[style*="rgba(60,60,67,0.3)"] { color: rgba(60,60,67,0.65) !important; }
[style*="rgba(0,0,0,0.4)"] { color: rgba(0,0,0,0.72) !important; }
[style*="rgba(0,0,0,0.3)"] { color: rgba(0,0,0,0.72) !important; }
[style*="opacity: 0.4"] { opacity: 0.72 !important; }
[style*="opacity: 0.3"] { opacity: 0.72 !important; }
@media (max-width: 640px) {
.hero h1 { font-size: 2rem !important; }
.hero p { font-size: 1rem !important; }
.card { padding: 1.5rem !important; }
.grid { grid-template-columns: 1fr !important; }
.btn { padding: 0.75rem 1.5rem !important; font-size: 1rem !important; }
}
</style>
</head>
<body>
<!-- NAV -->
<nav class="nav-bar">
<div class="nav-top">
<div class="nav-brand">
<div class="brand-icon">LX</div>
<span class="brand-label">LandveX</span>
</div>
<span class="badge-inspector">INSPEKTÖR</span>
<div style="width:32px;height:32px;border-radius: var(--radius-full);background:linear-gradient(135deg,#5856D6,#AF52DE);display:flex;align-items:center;justify-content:center;color:white;font-size:14px;font-weight:700;">M</div>
</div>
</nav>
<!-- DAILY MISSIONS -->
<div class="date-header">Måndag 18 maj 2026</div>
<div class="day-title">Dagens uppdrag</div>
<!-- MISSION 1 -->
<div class="mission-card">
<div class="mission-header">
<div>
<div class="mission-title">E4 Norrtull Avsnitt 12</div>
<div class="mission-sub"> Ytinspektion · Stockholm</div>
</div>
<div class="mission-number">1</div>
</div>
<div class="mission-body">
<div class="mission-row">
<div class="mission-row-icon"></div>
<div class="mission-row-label">Starttid</div>
<div class="mission-row-value">09:00</div>
</div>
<div class="mission-row">
<div class="mission-row-icon"></div>
<div class="mission-row-label">Beräknad tid</div>
<div class="mission-row-value">90 min</div>
</div>
<div class="mission-row">
<div class="mission-row-icon"></div>
<div class="mission-row-label">Plats</div>
<div class="mission-row-value">E4, km 164166</div>
</div>
<div class="mission-row">
<div class="mission-row-icon"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="3" y="2" width="10" height="12" rx="1" stroke="#666" stroke-width="1.5"/><path d="M6 5H10M6 8H10M6 11H8" stroke="#666" stroke-width="1.5" stroke-linecap="round"/></svg></div>
<div class="mission-row-label">Typ</div>
<div class="mission-row-value">Standard ytinspektion</div>
</div>
</div>
<div class="mission-actions">
<button class="btn-start" onclick="startMission(1)"> Starta uppdrag</button>
<button class="btn-nav" onclick="navigate('E4 Norrtull')"> Navigera</button>
</div>
</div>
<!-- MISSION 2 -->
<div class="mission-card">
<div class="mission-header">
<div>
<div class="mission-title">Kungliga Slottet Tak</div>
<div class="mission-sub"> Takinspektion · Kritisk · Stockholm</div>
</div>
<div class="mission-number" style="background:linear-gradient(135deg,#FF3B30,#CC1100)">2</div>
</div>
<div class="mission-body">
<div class="mission-row">
<div class="mission-row-icon"></div>
<div class="mission-row-label">Starttid</div>
<div class="mission-row-value">13:00</div>
</div>
<div class="mission-row">
<div class="mission-row-icon"></div>
<div class="mission-row-label">Beräknad tid</div>
<div class="mission-row-value">120 min</div>
</div>
<div class="mission-row">
<div class="mission-row-icon"></div>
<div class="mission-row-label">Plats</div>
<div class="mission-row-value">Kungliga Slottet, Gamla Stan</div>
</div>
<div class="mission-row">
<div class="mission-row-icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg></div>
<div class="mission-row-label">Prioritet</div>
<div class="mission-row-value" style="color:var(--ios-red);font-weight:600">KRITISK</div>
</div>
</div>
<div class="mission-actions">
<button class="btn-start" onclick="startMission(2)" style="background:var(--ios-red)"> Starta uppdrag</button>
<button class="btn-nav" onclick="navigate('Kungliga Slottet')"> Navigera</button>
</div>
</div>
<!-- PROGRESS -->
<div style="padding: 8px 16px 0;">
<div class="progress-wrap" style="padding: 0;">
<div class="progress-header">
<span>Daglig progress</span>
<span>0 / 2 uppdrag klara</span>
</div>
<div class="progress-track">
<div class="progress-fill" id="dayProgress" style="width:0%"></div>
</div>
</div>
</div>
<!-- INSPECTION FORM -->
<div class="form-section" id="inspectionForm" style="display:none;">
<div class="section-title"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="3" y="2" width="10" height="12" rx="1" stroke="#666" stroke-width="1.5"/><path d="M6 5H10M6 8H10M6 11H8" stroke="#666" stroke-width="1.5" stroke-linecap="round"/></svg> Inspektionsprotokoll</div>
<div class="form-card" style="margin-bottom:12px;">
<div class="form-row">
<div class="form-row-label">Objekt</div>
<input class="form-row-input" type="text" id="objektNamn" placeholder="Välj objekt..." readonly>
</div>
<div class="form-row">
<div class="form-row-label">Inspektionstyp</div>
<select class="form-row-select" id="inspType">
<option>Ytinspektion</option>
<option>Strukturkontroll</option>
<option>Takinspektion</option>
<option>Fasadinspektion</option>
</select>
</div>
<div class="form-row">
<div class="form-row-label">Datum</div>
<input class="form-row-input" type="date" id="inspDate" value="2026-05-18">
</div>
<div class="form-row">
<div class="form-row-label">Väder</div>
<select class="form-row-select">
<option> Klart</option>
<option> Molnigt</option>
<option> Regn</option>
<option> Snö</option>
<option> Blåsigt</option>
</select>
</div>
<div class="form-row">
<div class="form-row-label">Riskbedömning</div>
<select class="form-row-select" id="riskLevel">
<option value="low"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#00C853" stroke-width="3"><path d="M20 6L9 17l-5-5"/></svg> Låg (030)</option>
<option value="medium"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg> Medium (3165)</option>
<option value="high"> Hög (66100)</option>
</select>
</div>
</div>
<!-- CHECKLIST -->
<div style="font-size:13px;font-weight:600;color:var(--label-secondary);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:6px;padding:0 4px;">Checklista</div>
<div class="form-card" style="margin-bottom:12px;">
<div class="checklist-item" onclick="toggleCheck(this)">
<div class="check-box"><span class="check-mark"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div>
<div class="checklist-text">Yttre skador dokumenterade</div>
</div>
<div class="checklist-item" onclick="toggleCheck(this)">
<div class="check-box"><span class="check-mark"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div>
<div class="checklist-text">Strukturell integritet kontrollerad</div>
</div>
<div class="checklist-item" onclick="toggleCheck(this)">
<div class="check-box"><span class="check-mark"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div>
<div class="checklist-text">Dränering och avlopp inspekterade</div>
</div>
<div class="checklist-item" onclick="toggleCheck(this)">
<div class="check-box"><span class="check-mark"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div>
<div class="checklist-text">Korrosion och fuktskador noterade</div>
</div>
<div class="checklist-item" onclick="toggleCheck(this)">
<div class="check-box"><span class="check-mark"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div>
<div class="checklist-text">Säkerhetsrisker bedömda</div>
</div>
<div class="checklist-item" onclick="toggleCheck(this)">
<div class="check-box"><span class="check-mark"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span></div>
<div class="checklist-text">Jämförelse med föregående inspektion</div>
</div>
</div>
<!-- PHOTOS -->
<div style="font-size:13px;font-weight:600;color:var(--label-secondary);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:6px;padding:0 4px;">Foto (min 3 st)</div>
<div class="form-card" style="margin-bottom:12px;">
<div class="photo-grid">
<div class="photo-thumb" onclick="addPhoto(this)">
<div class="photo-placeholder"></div>
</div>
<div class="photo-thumb" onclick="addPhoto(this)">
<div class="photo-placeholder"></div>
</div>
<div class="photo-thumb add-photo" onclick="takePhoto()">
<div class="add-icon">+</div>
<div class="add-label">Lägg till</div>
</div>
</div>
<div style="padding:0 16px 12px;font-size:12px;color:var(--label-tertiary);">
Foton lagras säkert och bifogas rapporten automatiskt.
</div>
</div>
<!-- NOTES -->
<div style="font-size:13px;font-weight:600;color:var(--label-secondary);text-transform:uppercase;letter-spacing:0.5px;margin-bottom:6px;padding:0 4px;">Observationer & anteckningar</div>
<div class="form-card" style="margin-bottom:12px;">
<div class="form-textarea-wrap">
<textarea class="form-textarea" placeholder="Beskriv observationer, avvikelser och rekommenderade åtgärder...
Exempel:
- Sprickor identifierade på nordvästra hörn (20 cm lång, 23 mm bred)
- Fuktinträngning synlig under bro-sektionens ände
- Rekommendation: Täta sprickor inom 14 dagar, följ upp om 30 dagar"></textarea>
</div>
</div>
<!-- SUBMIT -->
<div class="submit-area">
<button class="submit-btn" onclick="submitReport()">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> Skicka inspektionsrapport
</button>
<div class="submit-note">Rapporten skickas till LandveX och objektägaren. Du kan ej ändra efter inskickning.</div>
</div>
</div>
<!-- PLACEHOLDER WHEN NO FORM -->
<div id="formPlaceholder" style="padding: 32px 16px; text-align: center; color: var(--label-tertiary);">
<div style="font-size: 48px; margin-bottom: 12px;"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="3" y="2" width="10" height="12" rx="1" stroke="#666" stroke-width="1.5"/><path d="M6 5H10M6 8H10M6 11H8" stroke="#666" stroke-width="1.5" stroke-linecap="round"/></svg></div>
<div style="font-size: 17px; font-weight: 600; color: var(--label-secondary);">Protokollformulär</div>
<div style="font-size: 14px; margin-top: 6px;">Starta ett uppdrag ovan för att öppna inspektionsformuläret.</div>
</div>
<!-- TAB BAR -->
<nav class="tab-bar">
<div class="tab-item active">
<div class="tab-icon"></div>
<div class="tab-label">Uppdrag</div>
</div>
<div class="tab-item" onclick="showForm()">
<div class="tab-icon"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="3" y="2" width="10" height="12" rx="1" stroke="#666" stroke-width="1.5"/><path d="M6 5H10M6 8H10M6 11H8" stroke="#666" stroke-width="1.5" stroke-linecap="round"/></svg></div>
<div class="tab-label">Protokoll</div>
</div>
<div class="tab-item">
<div class="tab-icon notif-dot"></div>
<div class="tab-label">Notiser</div>
</div>
<div class="tab-item">
<div class="tab-icon"></div>
<div class="tab-label">Arkiv</div>
</div>
<div class="tab-item">
<div class="tab-icon"></div>
<div class="tab-label">Profil</div>
</div>
</nav>
<script>
let completedMissions = 0;
function startMission(n) {
const missions = {
1: 'E4 Norrtull Avsnitt 12',
2: 'Kungliga Slottet Tak'
};
const form = document.getElementById('inspectionForm');
const placeholder = document.getElementById('formPlaceholder');
document.getElementById('objektNamn').value = missions[n];
form.style.display = 'block';
placeholder.style.display = 'none';
// Scroll to form
setTimeout(() => form.scrollIntoView({ behavior: 'smooth' }), 100);
// Feedback
const toast = document.createElement('div');
toast.style.cssText = 'position:fixed;top:60px;left:50%;transform:translateX(-50%);background:#F2F2F7;color:white;padding:10px 18px;border-radius: var(--radius-xl);font-size:14px;font-weight:600;z-index:500;';
toast.textContent = ` Uppdrag ${n} startat`;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 2000);
}
function navigate(place) {
alert(`Öppnar navigation till:\n${place}\n\n(Integreras med Maps/Waze i produktion)`);
}
function toggleCheck(item) {
const box = item.querySelector('.check-box');
const text = item.querySelector('.checklist-text');
box.classList.toggle('checked');
text.classList.toggle('checked');
updateProgress();
}
function updateProgress() {
const checked = document.querySelectorAll('.check-box.checked').length;
const total = document.querySelectorAll('.check-box').length;
const pct = total > 0 ? Math.round((checked / total) * 100) : 0;
document.getElementById('dayProgress').style.width = pct + '%';
}
function addPhoto(thumb) {
// Simulate photo capture
const emojis = ['','<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M2 14H14M4 14V8L8 4L12 8V14" stroke="#666" stroke-width="1.5" stroke-linejoin="round"/><path d="M6 14V10H10V14" stroke="#666" stroke-width="1.5"/></svg>','<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>','','',''];
thumb.innerHTML = `<div style="font-size:32px">${emojis[Math.floor(Math.random()*emojis.length)]}</div>`;
thumb.style.background = 'var(--fill-tertiary)';
}
function takePhoto() {
const grid = document.querySelector('.photo-grid');
const addBtn = grid.querySelector('.add-photo');
const newThumb = document.createElement('div');
newThumb.className = 'photo-thumb';
newThumb.onclick = function() { addPhoto(this); };
const emojis = ['','<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M2 14H14M4 14V8L8 4L12 8V14" stroke="#666" stroke-width="1.5" stroke-linejoin="round"/><path d="M6 14V10H10V14" stroke="#666" stroke-width="1.5"/></svg>','','','<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="7" cy="7" r="5" stroke="#666" stroke-width="2"/><path d="M11 11L14 14" stroke="#666" stroke-width="2" stroke-linecap="round"/></svg>',''];
newThumb.innerHTML = `<div style="font-size:32px">${emojis[Math.floor(Math.random()*emojis.length)]}</div>`;
newThumb.style.background = 'var(--fill-secondary)';
grid.insertBefore(newThumb, addBtn);
}
function showForm() {
document.getElementById('inspectionForm').style.display = 'block';
document.getElementById('formPlaceholder').style.display = 'none';
document.getElementById('inspectionForm').scrollIntoView({ behavior: 'smooth' });
}
function submitReport() {
const objekt = document.getElementById('objektNamn').value;
if (!objekt) {
alert('Välj ett objekt och starta uppdrag först.');
return;
}
const confirmed = confirm(`Skicka inspektionsrapport?\n\nObjekt: ${objekt}\nDatum: ${document.getElementById('inspDate').value}\n\nRapporten kan inte ändras efter inskickning.`);
if (confirmed) {
completedMissions++;
// Update progress
const pct = Math.min(completedMissions / 2 * 100, 100);
document.getElementById('dayProgress').style.width = pct + '%';
// Hide form
document.getElementById('inspectionForm').style.display = 'none';
document.getElementById('formPlaceholder').style.display = 'block';
// Feedback
const toast = document.createElement('div');
toast.style.cssText = 'position:fixed;bottom:80px;left:50%;transform:translateX(-50%);background:var(--ios-green);color:white;padding:14px 24px;border-radius: var(--radius-xl);font-size:15px;font-weight:600;z-index:500;box-shadow:0 4px 20px rgba(52,199,89,0.4);text-align:center;';
toast.innerHTML = `<svg width="16" height="16" viewBox="0 0 16 16" fill="none"><path d="M3 8L6.5 11.5L13 4.5" stroke="#22c55e" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> Rapport inskickad<br><span style="font-size:12px;opacity:0.85">${objekt}</span>`;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 3000);
// Scroll top
window.scrollTo({ top: 0, behavior: 'smooth' });
}
}
// Tab switching
document.querySelectorAll('.tab-item').forEach(tab => {
tab.addEventListener('click', () => {
document.querySelectorAll('.tab-item').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
});
});
</script>
</body>
</html>