Files
boc/landvex-all/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

901 lines
27 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" >
<link rel="stylesheet" href="/assets/css/landvex-complete.css">
<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: 16px;
}
.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: 24px;
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: 24px 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: 24px 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: 24px;
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: 16px;
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: 24px;
display: flex;
gap: 16px;
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: 24px;
border-bottom: 0.5px solid var(--separator);
gap: 16px;
}
.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: 24px;
}
.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: 24px;
border-bottom: 0.5px solid var(--separator);
gap: 16px;
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: 16px;
padding: 24px;
}
.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: 16px;
}
.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: 24px 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: 16px;
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" aria-label="Main navigation">
<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>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">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">KRITISK</div>
</div>
</div>
<div class="mission-actions">
<button class="btn-start" onclick="startMission(2)"> Starta uppdrag</button>
<button class="btn-nav" onclick="navigate('Kungliga Slottet')"> Navigera</button>
</div>
</div>
<!-- PROGRESS -->
<div>
<div class="progress-wrap">
<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"></div>
</div>
</div>
</div>
<!-- INSPECTION FORM -->
<div class="form-section" id="inspectionForm">
<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">
<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>Checklista</div>
<div class="form-card">
<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>Foto (min 3 st)</div>
<div class="form-card">
<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>
Foton lagras säkert och bifogas rapporten automatiskt.
</div>
</div>
<!-- NOTES -->
<div>Observationer & anteckningar</div>
<div class="form-card">
<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">
<div><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>Protokollformulär</div>
<div>Starta ett uppdrag ovan för att öppna inspektionsformuläret.</div>
</div>
<!-- TAB BAR -->
<nav class="tab-bar" aria-label="Main navigation">
<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: 24px;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>${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>${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: 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>${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>