feat: tighten line item review queue layout and scale
This commit is contained in:
parent
c19753ec04
commit
f2f2ac3310
|
|
@ -5763,3 +5763,323 @@ table {
|
|||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* ===== line item queue styled like document review ===== */
|
||||
.queue-review-card {
|
||||
padding: 1rem 1rem 0.95rem 1rem;
|
||||
border-radius: 1.5rem;
|
||||
box-shadow: 0 4px 18px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.queue-review-card .topbar {
|
||||
margin-bottom: 0.8rem !important;
|
||||
align-items: flex-start;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.queue-review-meta {
|
||||
font-size: 0.94rem;
|
||||
color: #6b7280;
|
||||
line-height: 1.25;
|
||||
margin-bottom: 0.12rem;
|
||||
}
|
||||
|
||||
.queue-review-title {
|
||||
margin: 0.1rem 0 0 0 !important;
|
||||
font-size: 1.15rem;
|
||||
line-height: 1.15;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.queue-review-raw {
|
||||
margin-top: 0.18rem;
|
||||
font-size: 0.96rem;
|
||||
color: #8a8f98;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.queue-review-badges {
|
||||
gap: 0.45rem;
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.queue-review-badges .badge {
|
||||
font-size: 0.84rem;
|
||||
padding: 0.32rem 0.7rem;
|
||||
}
|
||||
|
||||
.queue-review-form-grid {
|
||||
gap: 0.9rem;
|
||||
}
|
||||
|
||||
.queue-review-form-grid .form-field label {
|
||||
font-size: 0.92rem;
|
||||
margin-bottom: 0.35rem;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.queue-review-rating-input,
|
||||
.queue-review-note-input {
|
||||
border-radius: 1.1rem;
|
||||
}
|
||||
|
||||
.queue-review-rating-input {
|
||||
min-height: 3rem;
|
||||
}
|
||||
|
||||
.queue-review-note-input {
|
||||
min-height: 6.25rem;
|
||||
}
|
||||
|
||||
.queue-review-checkbox-row {
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.queue-review-checkbox-row label {
|
||||
margin: 0;
|
||||
font-size: 0.92rem;
|
||||
}
|
||||
|
||||
.queue-review-actions {
|
||||
gap: 0.6rem;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.queue-review-actions .button-link,
|
||||
.queue-review-actions button {
|
||||
min-height: 2.65rem;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.tab-panel[data-panel="queue"] > .card-title {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.tab-panel[data-panel="queue"] > .empty-state,
|
||||
.tab-panel[data-panel="queue"] .empty-state {
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.queue-review-card {
|
||||
padding: 0.95rem 0.95rem 0.9rem 0.95rem;
|
||||
}
|
||||
|
||||
.queue-review-card .topbar {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 0.55rem;
|
||||
}
|
||||
|
||||
.queue-review-title {
|
||||
font-size: 1.08rem;
|
||||
}
|
||||
|
||||
.queue-review-badges {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.queue-review-rating-input {
|
||||
min-height: 2.8rem;
|
||||
}
|
||||
|
||||
.queue-review-note-input {
|
||||
min-height: 5.2rem;
|
||||
}
|
||||
|
||||
.queue-review-actions {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
}
|
||||
/* ===== end line item queue styled like document review ===== */
|
||||
|
||||
|
||||
|
||||
|
||||
/* ===== line item queue header relayout ===== */
|
||||
.queue-review-card {
|
||||
padding: 0.82rem;
|
||||
border-radius: 1.35rem;
|
||||
}
|
||||
|
||||
.queue-review-header {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto auto;
|
||||
gap: 0.58rem;
|
||||
align-items: start;
|
||||
margin-bottom: 0.58rem;
|
||||
}
|
||||
|
||||
.queue-review-title-block {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.queue-review-meta {
|
||||
font-size: 0.78rem;
|
||||
color: #6b7280;
|
||||
line-height: 1.08;
|
||||
margin-bottom: 0.08rem;
|
||||
}
|
||||
|
||||
.queue-review-title {
|
||||
margin: 0 !important;
|
||||
font-size: 0.88rem;
|
||||
line-height: 1.02;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.queue-review-raw {
|
||||
margin-top: 0.12rem;
|
||||
font-size: 0.78rem;
|
||||
color: #8a8f98;
|
||||
line-height: 1.08;
|
||||
}
|
||||
|
||||
.queue-review-flags {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.18rem;
|
||||
align-self: start;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.queue-flag-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.28rem;
|
||||
font-size: 0.76rem;
|
||||
color: #4b5563;
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.queue-flag-row input[type="checkbox"] {
|
||||
width: 0.92rem;
|
||||
height: 0.92rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.queue-review-badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
gap: 0.28rem;
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
.queue-review-badges .badge {
|
||||
white-space: nowrap;
|
||||
font-size: 0.74rem;
|
||||
padding: 0.2rem 0.5rem;
|
||||
line-height: 1.05;
|
||||
}
|
||||
|
||||
.queue-review-body {
|
||||
display: grid;
|
||||
gap: 0.52rem;
|
||||
}
|
||||
|
||||
.queue-review-body .form-field label {
|
||||
font-size: 0.76rem;
|
||||
margin-bottom: 0.14rem;
|
||||
color: #6b7280;
|
||||
line-height: 1.05;
|
||||
}
|
||||
|
||||
.queue-review-rating-input,
|
||||
.queue-review-note-input {
|
||||
border-radius: 0.92rem;
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
.queue-review-rating-input {
|
||||
min-height: 2.35rem;
|
||||
}
|
||||
|
||||
.queue-review-note-input {
|
||||
min-height: 4.3rem;
|
||||
}
|
||||
|
||||
.queue-review-actions {
|
||||
margin-top: 0.62rem;
|
||||
gap: 0.42rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.queue-review-actions .button-link,
|
||||
.queue-review-actions button {
|
||||
min-height: 2.18rem;
|
||||
font-size: 0.82rem;
|
||||
padding: 0.48rem 0.9rem;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.queue-review-card {
|
||||
padding: 0.78rem;
|
||||
border-radius: 1.2rem;
|
||||
}
|
||||
|
||||
.queue-review-header {
|
||||
grid-template-columns: minmax(0, 1fr) auto auto;
|
||||
gap: 0.46rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.queue-review-meta {
|
||||
font-size: 0.74rem;
|
||||
}
|
||||
|
||||
.queue-review-title {
|
||||
font-size: 0.84rem;
|
||||
}
|
||||
|
||||
.queue-review-raw {
|
||||
font-size: 0.74rem;
|
||||
}
|
||||
|
||||
.queue-flag-row {
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
.queue-flag-row input[type="checkbox"] {
|
||||
width: 0.86rem;
|
||||
height: 0.86rem;
|
||||
}
|
||||
|
||||
.queue-review-badges .badge {
|
||||
font-size: 0.7rem;
|
||||
padding: 0.18rem 0.45rem;
|
||||
}
|
||||
|
||||
.queue-review-body .form-field label {
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
.queue-review-rating-input,
|
||||
.queue-review-note-input {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.queue-review-rating-input {
|
||||
min-height: 2.2rem;
|
||||
}
|
||||
|
||||
.queue-review-note-input {
|
||||
min-height: 3.9rem;
|
||||
}
|
||||
|
||||
.queue-review-actions .button-link,
|
||||
.queue-review-actions button {
|
||||
min-height: 2.05rem;
|
||||
font-size: 0.8rem;
|
||||
padding: 0.44rem 0.82rem;
|
||||
}
|
||||
}
|
||||
/* ===== end line item queue header relayout ===== */
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{% block title %}Document Processor{% endblock %}</title>
|
||||
<link rel="stylesheet" href="/static/app.css?v=161">
|
||||
<link rel="stylesheet" href="/static/app.css?v=166">
|
||||
<link rel="stylesheet" href="/static/app-shell.css?v=158">
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@
|
|||
<input type="hidden" name="rating_max" value="{{ rating_max }}">
|
||||
<input type="hidden" name="return_to" value="list">
|
||||
|
||||
<div class="form-grid">
|
||||
<div class="form-grid queue-review-form-grid">
|
||||
<div class="form-field">
|
||||
<label for="quality_rating_{{ row.line_item_id }}">Quality rating</label>
|
||||
<input id="quality_rating_{{ row.line_item_id }}" type="text" name="quality_rating" value="{{ row.quality_rating }}" placeholder="e.g. 8.5 or 4/5">
|
||||
|
|
@ -206,68 +206,66 @@
|
|||
|
||||
{% if queue_rows %}
|
||||
{% for row in queue_rows %}
|
||||
<div class="card" style="margin-bottom: 1rem;">
|
||||
<div class="topbar" style="margin-bottom: 0.75rem;">
|
||||
<div>
|
||||
<div class="page-subtitle">{{ row.transaction_date }} · {{ row.merchant }}</div>
|
||||
<h3 class="card-title" style="margin: 0.2rem 0 0 0;">{{ row.description }}</h3>
|
||||
<div class="page-subtitle">{{ row.raw_description }}</div>
|
||||
</div>
|
||||
<div class="badges">
|
||||
{% if row.category %}
|
||||
<span class="badge">{{ row.category }}</span>
|
||||
{% endif %}
|
||||
{% if row.quantity %}
|
||||
<span class="badge">Qty {{ row.quantity }}</span>
|
||||
{% endif %}
|
||||
{% if row.line_total %}
|
||||
<span class="badge">${{ row.line_total }}</span>
|
||||
{% endif %}
|
||||
{% if row.confidence %}
|
||||
<span class="badge">Conf {{ row.confidence }}</span>
|
||||
{% endif %}
|
||||
{% if row.quality_rating %}
|
||||
<span class="badge reviewed">Rating {{ row.quality_rating }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card queue-review-card" id="queue-item-{{ row.line_item_id }}">
|
||||
<form method="post" action="/line-items/{{ row.line_item_id }}/review">
|
||||
<input type="hidden" name="return_to" value="queue">
|
||||
|
||||
<form method="post" action="/line-items/{{ row.line_item_id }}/review">
|
||||
<input type="hidden" name="q" value="">
|
||||
<input type="hidden" name="merchant" value="">
|
||||
<input type="hidden" name="category" value="">
|
||||
<input type="hidden" name="date_from" value="">
|
||||
<input type="hidden" name="date_to" value="">
|
||||
<input type="hidden" name="rating_min" value="">
|
||||
<input type="hidden" name="rating_max" value="">
|
||||
<input type="hidden" name="return_to" value="queue">
|
||||
<div class="queue-review-header">
|
||||
<div class="queue-review-title-block">
|
||||
<div class="queue-review-meta">{{ row.transaction_date }} · {{ row.merchant }}</div>
|
||||
<h3 class="card-title queue-review-title">{{ row.description }}</h3>
|
||||
{% if row.raw_description and row.raw_description != row.description %}
|
||||
<div class="queue-review-raw">{{ row.raw_description }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="form-grid">
|
||||
<div class="form-field">
|
||||
<label for="queue_quality_rating_{{ row.line_item_id }}">Quality rating</label>
|
||||
<input id="queue_quality_rating_{{ row.line_item_id }}" type="text" name="quality_rating" value="{{ row.quality_rating }}" placeholder="e.g. 8.5 or 4/5">
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label>Review flags</label>
|
||||
<div style="display:flex; gap:0.75rem; flex-wrap:wrap; margin-top:0.35rem;">
|
||||
<label><input type="checkbox" name="is_approved" value="1" {% if row.is_approved %}checked{% endif %}> Approved</label>
|
||||
<label><input type="checkbox" name="is_excluded" value="1" {% if row.is_excluded %}checked{% endif %}> Excluded</label>
|
||||
<label><input type="checkbox" name="is_na" value="1" {% if row.is_na %}checked{% endif %} onchange="toggleReviewNA(this)"> N/A</label>
|
||||
<div class="queue-review-flags">
|
||||
<label class="queue-flag-row">
|
||||
<input type="checkbox" name="is_approved" value="1" {% if row.is_approved %}checked{% endif %}>
|
||||
<span>Approved</span>
|
||||
</label>
|
||||
<label class="queue-flag-row">
|
||||
<input type="checkbox" name="is_excluded" value="1" {% if row.is_excluded %}checked{% endif %}>
|
||||
<span>Excluded</span>
|
||||
</label>
|
||||
<label class="queue-flag-row">
|
||||
<input type="checkbox" name="is_na" value="1" {% if row.is_na %}checked{% endif %}>
|
||||
<span>N/A</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="badges queue-review-badges">
|
||||
{% if row.category %}
|
||||
<span class="badge">{{ row.category }}</span>
|
||||
{% endif %}
|
||||
{% if row.quantity %}
|
||||
<span class="badge">Qty {{ (row.quantity | string | replace(".0000", "") | replace(".00", "")) }}</span>
|
||||
{% endif %}
|
||||
{% if row.line_total %}
|
||||
<span class="badge">${{ "%.2f"|format(row.line_total|float) }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-field full">
|
||||
|
||||
<label for="queue_quality_note_{{ row.line_item_id }}">Quality note</label>
|
||||
<textarea id="queue_quality_note_{{ row.line_item_id }}" name="quality_note" rows="3" placeholder="Taste, portion, texture, service notes...">{{ row.quality_note }}</textarea>
|
||||
<div class="queue-review-body">
|
||||
<div class="form-field">
|
||||
<label for="queue_quality_rating_{{ row.line_item_id }}">Quality rating</label>
|
||||
<input id="queue_quality_rating_{{ row.line_item_id }}" class="queue-review-rating-input" type="text" name="quality_rating" value="{{ row.quality_rating }}" placeholder="e.g. 8.5 or 4/5">
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label for="queue_quality_note_{{ row.line_item_id }}">Quality note</label>
|
||||
<textarea id="queue_quality_note_{{ row.line_item_id }}" class="queue-review-note-input" name="quality_note" rows="3" placeholder="Taste, portion, texture, service notes...">{{ row.quality_note }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="button-row" style="margin-top: 1rem;">
|
||||
<button class="primary" type="submit">Save rating/note</button>
|
||||
<a class="button-link" href="/documents/{{ row.document_id }}?tab=line-items">Open document</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="button-row queue-review-actions">
|
||||
<button class="primary" type="submit">Save rating/note</button>
|
||||
<a class="button-link" href="/documents/{{ row.document_id }}?tab=line-items">Open document</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<p class="empty-state">No line items are waiting for quality review.</p>
|
||||
|
|
|
|||
Loading…
Reference in New Issue