b7e2d54bd2
Pass a 'next' hidden field from the device detail unassign form so the route redirects back to the device page instead of the dashboard.
146 lines
5.5 KiB
HTML
146 lines
5.5 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}{{ device.name }} — Battery Tracker{% endblock %}
|
||
|
||
{% block content %}
|
||
<h1>{{ device.name }}</h1>
|
||
|
||
<div class="card">
|
||
<table style="width:auto;border:none;">
|
||
<tr>
|
||
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Slots</td>
|
||
<td style="border:none;">{{ device.installed_count() }} / {{ device.battery_slots }} used</td>
|
||
</tr>
|
||
{% if device.has_mixed_brands() %}
|
||
<tr>
|
||
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Warning</td>
|
||
<td style="border:none;"><span class="badge badge-warning">⚠ Mixed brands installed</span></td>
|
||
</tr>
|
||
{% endif %}
|
||
{% if device.notes %}
|
||
<tr>
|
||
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Notes</td>
|
||
<td style="border:none;">{{ device.notes }}</td>
|
||
</tr>
|
||
{% endif %}
|
||
</table>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Install Batteries</h2>
|
||
{% set free_slots = device.battery_slots - device.installed_count() %}
|
||
<p class="text-muted" style="margin-bottom:0.75rem;">{{ free_slots }} slot(s) free</p>
|
||
<form method="post" action="{{ url_for('device_install', device_id=device.id) }}">
|
||
<div id="install-grid" style="display:grid;grid-template-columns:1fr auto;gap:0.4rem;max-width:400px;align-items:start;margin-bottom:0.5rem;">
|
||
<span style="font-weight:600;font-size:0.85rem;color:#64748b;">Brand</span>
|
||
<span style="font-weight:600;font-size:0.85rem;color:#64748b;">Qty</span>
|
||
<div class="install-row-pair" style="display:contents;">
|
||
<div>
|
||
<select onchange="brandSelectChanged(this)">
|
||
<option value="">— select —</option>
|
||
{% for b in brands|default([]) %}
|
||
<option value="{{ b }}">{{ b }}</option>
|
||
{% endfor %}
|
||
<option value="__new__">➕ New brand…</option>
|
||
</select>
|
||
<input type="text" name="brand[]" value=""
|
||
placeholder="Type brand name"
|
||
style="display:none;margin-top:0.3rem;padding:0.3rem 0.5rem;">
|
||
</div>
|
||
<input type="number" name="qty[]" value="0" min="0"
|
||
style="padding:0.3rem 0.5rem;width:4rem;text-align:center;">
|
||
</div>
|
||
</div>
|
||
<button type="button" class="btn btn-sm btn-secondary" onclick="addInstallRow()" style="margin-bottom:0.75rem;">+ Add brand</button>
|
||
<br>
|
||
<button class="btn btn-primary" type="submit">Install</button>
|
||
</form>
|
||
|
||
<script>
|
||
function brandSelectChanged(sel) {
|
||
var input = sel.nextElementSibling;
|
||
if (sel.value === '__new__') {
|
||
input.style.display = ''; input.value = ''; input.focus();
|
||
} else {
|
||
input.style.display = 'none';
|
||
input.value = (sel.value === '') ? '' : sel.value;
|
||
}
|
||
}
|
||
function addInstallRow() {
|
||
var grid = document.getElementById('install-grid');
|
||
var tmpl = grid.querySelector('.install-row-pair');
|
||
var clone = tmpl.cloneNode(true);
|
||
clone.querySelector('select').value = '';
|
||
clone.querySelector('input[type=text]').style.display = 'none';
|
||
clone.querySelector('input[type=text]').value = '';
|
||
clone.querySelector('input[type=number]').value = '0';
|
||
grid.appendChild(clone);
|
||
}
|
||
</script>
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Installed Batteries</h2>
|
||
{% set installed = device.batteries | selectattr('status', 'eq', 'installed') | list %}
|
||
{% if installed %}
|
||
<div class="table-wrap">
|
||
<table>
|
||
<thead>
|
||
<tr><th>Label</th><th>Brand</th><th>Notes</th><th>Actions</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for b in installed %}
|
||
<tr>
|
||
<td><a href="{{ url_for('battery_detail', battery_id=b.id) }}">{{ b.label }}</a></td>
|
||
<td>{{ b.brand }}</td>
|
||
<td class="text-muted">{{ b.notes or '—' }}</td>
|
||
<td>
|
||
<form class="inline" method="post" action="{{ url_for('battery_unassign', battery_id=b.id) }}">
|
||
<input type="hidden" name="next" value="{{ url_for('device_detail', device_id=device.id) }}">
|
||
<button class="btn btn-sm btn-warning" type="submit">Unassign</button>
|
||
</form>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{% else %}
|
||
<p class="text-muted">No batteries installed.</p>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Install Specific Battery</h2>
|
||
{% if available_batteries %}
|
||
<form method="post" action="{{ url_for('device_install_one', device_id=device.id) }}">
|
||
<div class="form-group">
|
||
<label for="battery_id">Battery</label>
|
||
<select name="battery_id" id="battery_id">
|
||
<option value="">— select —</option>
|
||
{% for b in available_batteries %}
|
||
<option value="{{ b.id }}">{{ b.label }} — {{ b.brand }}
|
||
{%- if b.size %} {{ b.size }}{% endif %}
|
||
{%- if b.notes %} ({{ b.notes }}){% endif %}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
<button class="btn btn-primary" type="submit">Install</button>
|
||
</form>
|
||
{% else %}
|
||
<p class="text-muted">No available batteries.</p>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div class="card">
|
||
<h2>Delete Device</h2>
|
||
<p style="margin-bottom:1rem;" class="text-muted">
|
||
Deleting this device will unassign all installed batteries and mark them available.
|
||
</p>
|
||
<form method="post" action="{{ url_for('device_delete', device_id=device.id) }}">
|
||
<button class="btn btn-danger" type="submit">Delete {{ device.name }}</button>
|
||
</form>
|
||
</div>
|
||
|
||
<a class="text-muted" href="{{ url_for('device_list') }}">← Back to Devices</a>
|
||
{% endblock %}
|