stage 1
This commit is contained in:
@@ -0,0 +1,347 @@
|
||||
<!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="stylesheet" href="/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<!--
|
||||
This document is the shared app shell for both operator and administrator
|
||||
routes. JavaScript decides which workspace to reveal based on the current
|
||||
URL so the project can keep one frontend bundle while still presenting two
|
||||
distinct entry points.
|
||||
-->
|
||||
<div class="app-shell">
|
||||
<aside class="sidebar panel">
|
||||
<!--
|
||||
The sidebar keeps app-level actions visible across both workspaces:
|
||||
sync status, template selection, navigation links, and the local draft
|
||||
list. That supports quick report switching on small operational screens.
|
||||
-->
|
||||
<div class="brand-block">
|
||||
<p class="eyebrow">Hybrid Inspection Reporting</p>
|
||||
<h1>Check List</h1>
|
||||
<p class="lede">
|
||||
Offline-first proof of concept for template-driven quality reports.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-section">
|
||||
<div class="status-row">
|
||||
<span id="connectionBadge" class="badge badge-neutral">Checking connection</span>
|
||||
<span id="saveBadge" class="badge badge-neutral">No changes</span>
|
||||
</div>
|
||||
<button id="syncTemplatesButton" class="button button-secondary" type="button">
|
||||
Sync templates
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-section">
|
||||
<label class="field-label" for="templateSelect">Template</label>
|
||||
<select id="templateSelect" class="select-input"></select>
|
||||
<button id="createReportButton" class="button button-primary" type="button">
|
||||
Create new report
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-section">
|
||||
<div class="section-heading-row sidebar-links-heading">
|
||||
<h2>Access</h2>
|
||||
<span class="muted-count">Direct links</span>
|
||||
</div>
|
||||
<a id="userAreaLink" class="button button-secondary sidebar-link" href="/user">User area</a>
|
||||
<a id="adminAreaLink" class="button button-secondary sidebar-link" href="/admin">Admin area</a>
|
||||
<a class="button button-secondary sidebar-link" href="/">Back to portal</a>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-section grow-section">
|
||||
<div class="section-heading-row">
|
||||
<h2>Local reports</h2>
|
||||
<span id="reportCount" class="muted-count">0</span>
|
||||
</div>
|
||||
<!-- F4 — Search and status filter for the local report list -->
|
||||
<div class="report-filter-row">
|
||||
<input id="reportSearchInput" class="text-input text-input-small" type="search" placeholder="Search reports" />
|
||||
<select id="reportFilterSelect" class="select-input select-input-small">
|
||||
<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 class="workspace">
|
||||
<!-- Operator workspace: draft editing, validation, and local attachments. -->
|
||||
<section id="reportsWorkspace" class="workspace-view workspace-view-active">
|
||||
<section class="hero panel">
|
||||
<div>
|
||||
<p class="eyebrow">Proof of concept frontend</p>
|
||||
<h2 id="heroTitle">No report selected</h2>
|
||||
<p id="heroSubtitle" class="hero-copy">
|
||||
Start by syncing templates and creating a local draft.
|
||||
</p>
|
||||
</div>
|
||||
<div class="hero-actions">
|
||||
<label class="status-picker">
|
||||
<span>Status</span>
|
||||
<select id="reportStatusSelect" class="select-input">
|
||||
<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="button button-secondary" type="button">
|
||||
Submit
|
||||
</button>
|
||||
<button id="exportReportButton" class="button button-secondary" type="button">
|
||||
Export CSV
|
||||
</button>
|
||||
<button id="deleteReportButton" class="button button-ghost" type="button">
|
||||
Delete report
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="summary-grid">
|
||||
<article class="summary-card panel accent-card">
|
||||
<p class="summary-label">Template</p>
|
||||
<strong id="summaryTemplate">Not loaded</strong>
|
||||
<span id="summaryVersion" class="summary-note">Version -</span>
|
||||
</article>
|
||||
<article class="summary-card panel">
|
||||
<p class="summary-label">Validation</p>
|
||||
<strong id="validationHeadline">No report selected</strong>
|
||||
<span id="validationDetail" class="summary-note">Draft validation will appear here.</span>
|
||||
</article>
|
||||
<article class="summary-card panel">
|
||||
<p class="summary-label">Offline cache</p>
|
||||
<strong id="syncHeadline">No sync yet</strong>
|
||||
<span id="syncDetail" class="summary-note">Templates are cached locally after the first successful sync.</span>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<section class="editor-grid">
|
||||
<section class="panel editor-panel">
|
||||
<div class="section-heading-row">
|
||||
<h2>Report editor</h2>
|
||||
<span id="editorHint" class="panel-note">Dynamic form rendering from template JSON</span>
|
||||
</div>
|
||||
<form id="reportForm" class="report-form">
|
||||
<div class="empty-state">
|
||||
<h3>No report open</h3>
|
||||
<p>Choose a template and create a report to start editing locally.</p>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<aside class="panel inspector-panel">
|
||||
<div class="section-heading-row">
|
||||
<h2>Inspector view</h2>
|
||||
<span class="panel-note">Local draft summary</span>
|
||||
</div>
|
||||
<dl id="reportMeta" class="meta-list">
|
||||
<div>
|
||||
<dt>Report ID</dt>
|
||||
<dd>-</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Template</dt>
|
||||
<dd>-</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Created</dt>
|
||||
<dd>-</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Updated</dt>
|
||||
<dd>-</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<div class="validation-block">
|
||||
<h3>Validation issues</h3>
|
||||
<ul id="validationList" class="validation-list">
|
||||
<li>No report selected.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="attachment-policy">
|
||||
<h3>Image policy</h3>
|
||||
<p id="imagePolicyText" class="policy-copy">
|
||||
Load server configuration to see image limits and optimization rules.
|
||||
</p>
|
||||
</div>
|
||||
</aside>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<!-- Administrator workspace: server-backed configuration editing. -->
|
||||
<section id="adminWorkspace" class="workspace-view" hidden>
|
||||
<section class="hero panel">
|
||||
<div>
|
||||
<p class="eyebrow">Administrator workspace</p>
|
||||
<h2>Configuration control</h2>
|
||||
<p class="hero-copy">
|
||||
Update centrally managed image requirements used by the inspection frontend.
|
||||
</p>
|
||||
</div>
|
||||
<div class="hero-actions">
|
||||
<span id="adminSyncState" class="badge badge-neutral">Server-backed settings</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="editor-grid">
|
||||
<section class="panel editor-panel">
|
||||
<div class="section-heading-row">
|
||||
<h2>Image policy editor</h2>
|
||||
<span class="panel-note">Updates the active server rule</span>
|
||||
</div>
|
||||
<form id="adminImageRulesForm" class="report-form admin-form">
|
||||
<section class="template-section">
|
||||
<div class="field-grid">
|
||||
<div class="field field-full">
|
||||
<div class="field-header">
|
||||
<label class="field-label" for="adminPolicyName">Policy name</label>
|
||||
</div>
|
||||
<input id="adminPolicyName" name="name" class="text-input" type="text" />
|
||||
</div>
|
||||
|
||||
<div class="field field-full">
|
||||
<div class="field-header">
|
||||
<label class="field-label" for="adminAllowedMimeTypes">Allowed MIME types</label>
|
||||
</div>
|
||||
<input
|
||||
id="adminAllowedMimeTypes"
|
||||
name="allowedMimeTypes"
|
||||
class="text-input"
|
||||
type="text"
|
||||
placeholder="image/jpeg, image/png, image/webp"
|
||||
/>
|
||||
<p class="field-help">Comma-separated values used by the attachment field and browser validation.</p>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-header">
|
||||
<label class="field-label" for="adminMaxFileSizeMb">Max file size (MB)</label>
|
||||
</div>
|
||||
<input id="adminMaxFileSizeMb" name="maxFileSizeMb" class="text-input" type="number" min="1" step="0.1" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-header">
|
||||
<label class="field-label" for="adminMaxAttachmentsPerField">Max attachments per field</label>
|
||||
</div>
|
||||
<input id="adminMaxAttachmentsPerField" name="maxAttachmentsPerField" class="text-input" type="number" min="1" step="1" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-header">
|
||||
<label class="field-label" for="adminMaxWidthPx">Max width (px)</label>
|
||||
</div>
|
||||
<input id="adminMaxWidthPx" name="maxWidthPx" class="text-input" type="number" min="1" step="1" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-header">
|
||||
<label class="field-label" for="adminMaxHeightPx">Max height (px)</label>
|
||||
</div>
|
||||
<input id="adminMaxHeightPx" name="maxHeightPx" class="text-input" type="number" min="1" step="1" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-header">
|
||||
<label class="field-label" for="adminJpegQuality">JPEG quality</label>
|
||||
</div>
|
||||
<input id="adminJpegQuality" name="jpegQuality" class="text-input" type="number" min="1" max="100" step="1" />
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="field-header">
|
||||
<label class="field-label" for="adminOversizeBehavior">Oversize behavior</label>
|
||||
</div>
|
||||
<select id="adminOversizeBehavior" name="oversizeBehavior" class="select-input">
|
||||
<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>
|
||||
</section>
|
||||
|
||||
<div class="admin-actions">
|
||||
<button id="saveImageRulesButton" class="button button-primary" type="submit">
|
||||
Save image policy
|
||||
</button>
|
||||
<button id="resetImageRulesButton" class="button button-secondary" type="button">
|
||||
Reset form
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<aside class="panel inspector-panel">
|
||||
<div class="section-heading-row">
|
||||
<h2>Admin summary</h2>
|
||||
<span class="panel-note">Live configuration preview</span>
|
||||
</div>
|
||||
|
||||
<dl class="meta-list">
|
||||
<div>
|
||||
<dt>Active policy code</dt>
|
||||
<dd id="adminPolicyCode">-</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Allowed types</dt>
|
||||
<dd id="adminPolicyMimeTypes">-</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Optimization</dt>
|
||||
<dd id="adminPolicyOptimization">-</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Limits</dt>
|
||||
<dd id="adminPolicyLimits">-</dd>
|
||||
</div>
|
||||
</dl>
|
||||
|
||||
<div class="validation-block">
|
||||
<h3>Admin notes</h3>
|
||||
<ul class="validation-list" id="adminNotesList">
|
||||
<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>
|
||||
</aside>
|
||||
</section>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
Report list items are rendered from this template at runtime so the sidebar
|
||||
can update without rebuilding the entire page markup from strings.
|
||||
-->
|
||||
<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>
|
||||
Reference in New Issue
Block a user