88 lines
3.5 KiB
HTML
88 lines
3.5 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}Brackets — POPS{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||
<h5 class="text-white mb-0">Job Brackets</h5>
|
||
<button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#addBracketModal">
|
||
<i class="bi bi-plus-lg me-1"></i>New Bracket
|
||
</button>
|
||
</div>
|
||
|
||
<div class="card">
|
||
{% if brackets %}
|
||
<table class="table table-dark table-hover mb-0 align-middle">
|
||
<thead>
|
||
<tr class="text-secondary small">
|
||
<th class="fw-normal">Name</th>
|
||
<th class="fw-normal">Customer</th>
|
||
<th class="fw-normal">Progress</th>
|
||
<th class="fw-normal text-end">Created</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for b in brackets %}
|
||
{% set total = b.jobs | length %}
|
||
{% set done = b.jobs | selectattr('status.value', 'in', ['done', 'cancelled']) | list | length %}
|
||
{% set pct = (done / total * 100) | int if total else 0 %}
|
||
<tr>
|
||
<td><a href="/jobs?bracket_id={{ b.id }}" class="text-white text-decoration-none fw-medium">{{ b.name }}</a></td>
|
||
<td class="text-secondary">{{ b.customer or '—' }}</td>
|
||
<td style="min-width:200px">
|
||
{% if total %}
|
||
<div class="d-flex align-items-center gap-2">
|
||
<div class="progress flex-grow-1" style="height:6px">
|
||
<div class="progress-bar bg-success" style="width:{{ pct }}%"></div>
|
||
</div>
|
||
<span class="text-secondary small">{{ done }}/{{ total }}</span>
|
||
</div>
|
||
{% else %}
|
||
<span class="text-secondary small">no jobs</span>
|
||
{% endif %}
|
||
</td>
|
||
<td class="text-secondary small text-end">{{ b.created_at.strftime('%d.%m.%Y') }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% else %}
|
||
<div class="card-body text-secondary">No brackets yet.</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
{# ── Create Bracket Modal ── #}
|
||
<div class="modal fade" id="addBracketModal" tabindex="-1">
|
||
<div class="modal-dialog">
|
||
<div class="modal-content bg-dark border-secondary">
|
||
<form method="POST" action="/brackets">
|
||
<div class="modal-header border-secondary">
|
||
<h6 class="modal-title text-white">New Job Bracket</h6>
|
||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||
</div>
|
||
<div class="modal-body d-flex flex-column gap-3">
|
||
<div>
|
||
<label class="form-label text-secondary small">Name <span class="text-danger">*</span></label>
|
||
<input type="text" name="name" class="form-control bg-dark border-secondary text-white"
|
||
placeholder="e.g. Chair set, 30× phone stand" required autofocus>
|
||
</div>
|
||
<div>
|
||
<label class="form-label text-secondary small">Customer</label>
|
||
<input type="text" name="customer" class="form-control bg-dark border-secondary text-white"
|
||
placeholder="Customer name or reference">
|
||
</div>
|
||
<div>
|
||
<label class="form-label text-secondary small">Notes</label>
|
||
<textarea name="notes" class="form-control bg-dark border-secondary text-white"
|
||
rows="2" placeholder="Optional notes"></textarea>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer border-secondary">
|
||
<button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancel</button>
|
||
<button type="submit" class="btn btn-primary btn-sm">Create</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|