280 lines
14 KiB
HTML
280 lines
14 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta name="theme-color" content="#f3efe6" />
|
|
<title>Check List PoC</title>
|
|
<link rel="manifest" href="/manifest.webmanifest" />
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" />
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet" />
|
|
<link rel="stylesheet" href="/styles.css" />
|
|
</head>
|
|
<body>
|
|
<div class="d-flex vh-100">
|
|
<!-- Sidebar -->
|
|
<aside class="sidebar-bs d-flex flex-column border-end bg-light" style="width:280px;min-width:280px;">
|
|
<div class="p-3 border-bottom">
|
|
<p class="text-uppercase text-muted small fw-semibold mb-0">Hybrid Inspection Reporting</p>
|
|
<h5 class="fw-bold mb-0">Check List</h5>
|
|
<small class="text-muted">Offline-first proof of concept for template-driven quality reports.</small>
|
|
</div>
|
|
|
|
<div class="p-3 border-bottom">
|
|
<div class="d-flex gap-2 mb-2">
|
|
<span id="connectionBadge" class="badge bg-secondary">Checking connection</span>
|
|
<span id="saveBadge" class="badge bg-secondary">No changes</span>
|
|
</div>
|
|
<button id="syncTemplatesButton" class="btn btn-outline-secondary btn-sm w-100" type="button">
|
|
<i class="bi bi-arrow-repeat me-1"></i>Sync templates
|
|
</button>
|
|
</div>
|
|
|
|
<div class="p-3 border-bottom">
|
|
<label class="form-label small fw-semibold" for="templateSelect">Template</label>
|
|
<select id="templateSelect" class="form-select form-select-sm mb-2"></select>
|
|
<button id="createReportButton" class="btn btn-primary btn-sm w-100" type="button">
|
|
<i class="bi bi-plus-lg me-1"></i>Create new report
|
|
</button>
|
|
</div>
|
|
|
|
<div class="p-3 border-bottom">
|
|
<a id="userAreaLink" class="btn btn-outline-secondary btn-sm w-100 mb-1" href="/user">User area</a>
|
|
<a id="adminAreaLink" class="btn btn-outline-secondary btn-sm w-100 mb-1" href="/admin">Admin area</a>
|
|
<a class="btn btn-outline-secondary btn-sm w-100" href="/">Back to portal</a>
|
|
</div>
|
|
|
|
<div class="flex-grow-1 overflow-auto p-3">
|
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
|
<h6 class="fw-semibold mb-0">Local reports</h6>
|
|
<span id="reportCount" class="badge bg-secondary">0</span>
|
|
</div>
|
|
<div class="mb-2">
|
|
<input id="reportSearchInput" class="form-control form-control-sm mb-1" type="search" placeholder="Search reports" />
|
|
<select id="reportFilterSelect" class="form-select form-select-sm">
|
|
<option value="">All statuses</option>
|
|
<option value="draft">Draft</option>
|
|
<option value="in_progress">In Progress</option>
|
|
<option value="ready_for_export">Ready for Export</option>
|
|
<option value="exported">Exported</option>
|
|
<option value="archived">Archived</option>
|
|
</select>
|
|
</div>
|
|
<div id="reportList" class="report-list"></div>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- Main content -->
|
|
<main class="flex-grow-1 overflow-auto p-4 bg-white">
|
|
|
|
<!-- Operator workspace -->
|
|
<section id="reportsWorkspace" class="workspace-view workspace-view-active">
|
|
<div class="d-flex justify-content-between align-items-start mb-4">
|
|
<div>
|
|
<p class="text-muted small mb-0">Proof of concept frontend</p>
|
|
<h3 id="heroTitle" class="fw-bold">No report selected</h3>
|
|
<p id="heroSubtitle" class="text-muted">Start by syncing templates and creating a local draft.</p>
|
|
</div>
|
|
<div class="d-flex gap-2 align-items-center">
|
|
<label class="d-flex align-items-center gap-1 small">
|
|
<span>Status</span>
|
|
<select id="reportStatusSelect" class="form-select form-select-sm" style="width:auto">
|
|
<option value="draft">Draft</option>
|
|
<option value="in_progress">In Progress</option>
|
|
<option value="ready_for_export">Ready for Export</option>
|
|
<option value="exported">Exported</option>
|
|
<option value="archived">Archived</option>
|
|
</select>
|
|
</label>
|
|
<button id="submitReportButton" class="btn btn-outline-secondary btn-sm" type="button">Submit</button>
|
|
<button id="exportReportButton" class="btn btn-outline-secondary btn-sm" type="button">Export CSV</button>
|
|
<button id="deleteReportButton" class="btn btn-outline-danger btn-sm" type="button">Delete</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Summary cards -->
|
|
<div class="row g-3 mb-4">
|
|
<div class="col-md-4">
|
|
<div class="card border-primary">
|
|
<div class="card-body py-2 px-3">
|
|
<small class="text-muted">Template</small>
|
|
<div class="fw-semibold" id="summaryTemplate">Not loaded</div>
|
|
<small class="text-muted" id="summaryVersion">Version -</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="card">
|
|
<div class="card-body py-2 px-3">
|
|
<small class="text-muted">Validation</small>
|
|
<div class="fw-semibold" id="validationHeadline">No report selected</div>
|
|
<small class="text-muted" id="validationDetail">Draft validation will appear here.</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="card">
|
|
<div class="card-body py-2 px-3">
|
|
<small class="text-muted">Offline cache</small>
|
|
<div class="fw-semibold" id="syncHeadline">No sync yet</div>
|
|
<small class="text-muted" id="syncDetail">Templates are cached locally after the first successful sync.</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Editor + Inspector -->
|
|
<div class="row g-4">
|
|
<div class="col-lg-8">
|
|
<div class="card">
|
|
<div class="card-header d-flex justify-content-between align-items-center">
|
|
<h6 class="mb-0 fw-semibold">Report editor</h6>
|
|
<small id="editorHint" class="text-muted">Dynamic form rendering from template JSON</small>
|
|
</div>
|
|
<div class="card-body">
|
|
<form id="reportForm" class="report-form">
|
|
<div class="text-center text-muted py-4">
|
|
<h5>No report open</h5>
|
|
<p>Choose a template and create a report to start editing locally.</p>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-4">
|
|
<div class="card mb-3">
|
|
<div class="card-header fw-semibold">Inspector view</div>
|
|
<div class="card-body">
|
|
<dl id="reportMeta" class="mb-0">
|
|
<dt class="small text-muted">Report ID</dt><dd class="mb-2">-</dd>
|
|
<dt class="small text-muted">Template</dt><dd class="mb-2">-</dd>
|
|
<dt class="small text-muted">Created</dt><dd class="mb-2">-</dd>
|
|
<dt class="small text-muted">Updated</dt><dd class="mb-0">-</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
<div class="card mb-3">
|
|
<div class="card-header fw-semibold">Validation issues</div>
|
|
<div class="card-body">
|
|
<ul id="validationList" class="mb-0 ps-3">
|
|
<li>No report selected.</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="card">
|
|
<div class="card-header fw-semibold">Image policy</div>
|
|
<div class="card-body">
|
|
<p id="imagePolicyText" class="mb-0 text-muted small">
|
|
Load server configuration to see image limits and optimization rules.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Admin workspace (legacy) -->
|
|
<section id="adminWorkspace" class="workspace-view" hidden>
|
|
<div class="mb-4">
|
|
<p class="text-muted small mb-0">Administrator workspace</p>
|
|
<h3 class="fw-bold">Configuration control</h3>
|
|
<p class="text-muted">Update centrally managed image requirements used by the inspection frontend.</p>
|
|
<span id="adminSyncState" class="badge bg-secondary">Server-backed settings</span>
|
|
</div>
|
|
|
|
<div class="row g-4">
|
|
<div class="col-lg-8">
|
|
<div class="card">
|
|
<div class="card-header fw-semibold">Image policy editor</div>
|
|
<div class="card-body">
|
|
<form id="adminImageRulesForm">
|
|
<div class="row g-3 mb-3">
|
|
<div class="col-12">
|
|
<label for="adminPolicyName" class="form-label">Policy name</label>
|
|
<input id="adminPolicyName" name="name" class="form-control" type="text" />
|
|
</div>
|
|
<div class="col-12">
|
|
<label for="adminAllowedMimeTypes" class="form-label">Allowed MIME types</label>
|
|
<input id="adminAllowedMimeTypes" name="allowedMimeTypes" class="form-control" type="text" placeholder="image/jpeg, image/png, image/webp" />
|
|
<div class="form-text">Comma-separated values used by the attachment field and browser validation.</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label for="adminMaxFileSizeMb" class="form-label">Max file size (MB)</label>
|
|
<input id="adminMaxFileSizeMb" name="maxFileSizeMb" class="form-control" type="number" min="1" step="0.1" />
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label for="adminMaxAttachmentsPerField" class="form-label">Max attachments per field</label>
|
|
<input id="adminMaxAttachmentsPerField" name="maxAttachmentsPerField" class="form-control" type="number" min="1" step="1" />
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label for="adminMaxWidthPx" class="form-label">Max width (px)</label>
|
|
<input id="adminMaxWidthPx" name="maxWidthPx" class="form-control" type="number" min="1" step="1" />
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label for="adminMaxHeightPx" class="form-label">Max height (px)</label>
|
|
<input id="adminMaxHeightPx" name="maxHeightPx" class="form-control" type="number" min="1" step="1" />
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label for="adminJpegQuality" class="form-label">JPEG quality</label>
|
|
<input id="adminJpegQuality" name="jpegQuality" class="form-control" type="number" min="1" max="100" step="1" />
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label for="adminOversizeBehavior" class="form-label">Oversize behavior</label>
|
|
<select id="adminOversizeBehavior" name="oversizeBehavior" class="form-select">
|
|
<option value="auto_optimize">Auto optimize</option>
|
|
<option value="warn_then_optimize">Warn then optimize</option>
|
|
<option value="block">Block oversized files</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="d-flex gap-2">
|
|
<button id="saveImageRulesButton" class="btn btn-primary" type="submit">Save image policy</button>
|
|
<button id="resetImageRulesButton" class="btn btn-outline-secondary" type="button">Reset form</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-4">
|
|
<div class="card">
|
|
<div class="card-header fw-semibold">Admin summary</div>
|
|
<div class="card-body">
|
|
<dl class="mb-0">
|
|
<dt class="small text-muted">Active policy code</dt><dd id="adminPolicyCode" class="mb-2">-</dd>
|
|
<dt class="small text-muted">Allowed types</dt><dd id="adminPolicyMimeTypes" class="mb-2">-</dd>
|
|
<dt class="small text-muted">Optimization</dt><dd id="adminPolicyOptimization" class="mb-2">-</dd>
|
|
<dt class="small text-muted">Limits</dt><dd id="adminPolicyLimits" class="mb-0">-</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
<div class="card mt-3">
|
|
<div class="card-header fw-semibold">Admin notes</div>
|
|
<div class="card-body">
|
|
<ul id="adminNotesList" class="mb-0 ps-3">
|
|
<li>Changes are stored on the server and reused by report attachments.</li>
|
|
<li>Operators will use the updated policy after the next sync.</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</div>
|
|
|
|
<template id="reportListItemTemplate">
|
|
<button class="report-list-item" type="button" data-report-id="">
|
|
<span class="report-list-item__header">
|
|
<strong class="report-list-item__title"></strong>
|
|
<span class="report-list-item__status badge"></span>
|
|
</span>
|
|
<span class="report-list-item__meta"></span>
|
|
</button>
|
|
</template>
|
|
|
|
<script type="module" src="/app.js"></script>
|
|
</body>
|
|
</html> |