3bc897c1e5
- Device model: add device_type column (String 50, nullable) - Device add/edit: type select with presets + custom entry - Device detail: show type in info card; new Edit Device form - Device list: Type column + client-side filter bar (type + text search) - Mobile: card-style responsive tables on dashboard and device list, form-grid-2col collapse, larger tap targets, stacked form-actions, column picker viewport fix, filter bar full-width controls - Assign page: larger radio touch targets (min-height 44px) - 3 new acceptance tests for device_type (45 total)
214 lines
9.1 KiB
HTML
214 lines
9.1 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}{{ battery.label }} — Battery Tracker{% endblock %}
|
||
|
||
{% block content %}
|
||
<h1>{{ battery.label }}</h1>
|
||
|
||
{% macro meta_row(label, value) %}
|
||
{% if value %}
|
||
<tr>
|
||
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">{{ label }}</td>
|
||
<td style="border:none;">{{ value }}</td>
|
||
</tr>
|
||
{% endif %}
|
||
{% endmacro %}
|
||
|
||
<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;">Label</td>
|
||
<td style="border:none;">{{ battery.label }}</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Brand</td>
|
||
<td style="border:none;">{{ battery.brand }}</td>
|
||
</tr>
|
||
<tr>
|
||
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Status</td>
|
||
<td style="border:none;"><span class="badge badge-{{ battery.status }}">{{ battery.status|capitalize }}</span></td>
|
||
</tr>
|
||
<tr>
|
||
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Device</td>
|
||
<td style="border:none;">
|
||
{% if battery.device %}
|
||
<a href="{{ url_for('device_detail', device_id=battery.device.id) }}">{{ battery.device.name }}</a>
|
||
{% else %}
|
||
<span class="text-muted">None</span>
|
||
{% endif %}
|
||
</td>
|
||
</tr>
|
||
{{ meta_row("Size", battery.size) }}
|
||
{{ meta_row("Chemistry", battery.chemistry) }}
|
||
{% if battery.capacity_mah %}
|
||
<tr>
|
||
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Capacity</td>
|
||
<td style="border:none;">
|
||
{{ battery.capacity_mah }} mAh
|
||
{% if battery.tested_capacity_mah %}
|
||
{% set pct = (battery.tested_capacity_mah / battery.capacity_mah * 100)|round|int %}
|
||
{% if pct >= 80 %}{% set health_color = "#166534" %}
|
||
{% elif pct >= 60 %}{% set health_color = "#92400e" %}
|
||
{% else %}{% set health_color = "#991b1b" %}
|
||
{% endif %}
|
||
→ tested <strong style="color:{{ health_color }};">{{ battery.tested_capacity_mah }} mAh ({{ pct }}%)</strong>
|
||
{% if battery.tested_date %}<span class="text-muted">on {{ battery.tested_date }}</span>{% endif %}
|
||
{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% elif battery.tested_capacity_mah %}
|
||
<tr>
|
||
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Tested Capacity</td>
|
||
<td style="border:none;">
|
||
{{ battery.tested_capacity_mah }} mAh
|
||
{% if battery.tested_date %}<span class="text-muted">on {{ battery.tested_date }}</span>{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% endif %}
|
||
{{ meta_row("Charge Cycles", battery.charge_cycles) }}
|
||
{{ meta_row("Purchase Date", battery.purchase_date) }}
|
||
{{ meta_row("Storage", battery.storage_location) }}
|
||
{% if battery.notes %}
|
||
<tr>
|
||
<td style="padding:0.3rem 1rem 0.3rem 0;font-weight:600;color:#64748b;border:none;">Notes</td>
|
||
<td style="border:none;">{{ battery.notes }}</td>
|
||
</tr>
|
||
{% endif %}
|
||
</table>
|
||
</div>
|
||
|
||
<!-- Edit Details -->
|
||
<div class="card">
|
||
<h2>Edit Details</h2>
|
||
<form method="post" action="{{ url_for('battery_edit_details', battery_id=battery.id) }}">
|
||
|
||
<div class="form-grid-2col" style="display:grid;grid-template-columns:1fr 1fr;gap:0 1rem;">
|
||
|
||
<div class="form-group">
|
||
<label>Size</label>
|
||
<select id="size-select" onchange="metaSelectChanged(this,'size')">
|
||
<option value="">— none —</option>
|
||
{% for opt in ['AA','AAA','C','D','9V','18650','21700','14500','26650','CR2032','CR123A'] %}
|
||
<option value="{{ opt }}" {% if battery.size == opt %}selected{% endif %}>{{ opt }}</option>
|
||
{% endfor %}
|
||
<option value="__new__" {% if battery.size and battery.size not in ['AA','AAA','C','D','9V','18650','21700','14500','26650','CR2032','CR123A'] %}selected{% endif %}>Other…</option>
|
||
</select>
|
||
<input type="text" id="size" name="size" value="{{ battery.size or '' }}"
|
||
placeholder="Enter size"
|
||
style="display:{% if battery.size and battery.size not in ['AA','AAA','C','D','9V','18650','21700','14500','26650','CR2032','CR123A'] %}''{% else %}none{% endif %};margin-top:0.4rem;">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Chemistry</label>
|
||
<select id="chemistry-select" onchange="metaSelectChanged(this,'chemistry')">
|
||
<option value="">— none —</option>
|
||
{% for opt in ['NiMH','Alkaline','Li-ion','LiFePO4','NiCd','Zinc-Carbon','Li-MnO2'] %}
|
||
<option value="{{ opt }}" {% if battery.chemistry == opt %}selected{% endif %}>{{ opt }}</option>
|
||
{% endfor %}
|
||
<option value="__new__" {% if battery.chemistry and battery.chemistry not in ['NiMH','Alkaline','Li-ion','LiFePO4','NiCd','Zinc-Carbon','Li-MnO2'] %}selected{% endif %}>Other…</option>
|
||
</select>
|
||
<input type="text" id="chemistry" name="chemistry" value="{{ battery.chemistry or '' }}"
|
||
placeholder="Enter chemistry"
|
||
style="display:{% if battery.chemistry and battery.chemistry not in ['NiMH','Alkaline','Li-ion','LiFePO4','NiCd','Zinc-Carbon','Li-MnO2'] %}''{% else %}none{% endif %};margin-top:0.4rem;">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="capacity_mah">Capacity (mAh)</label>
|
||
<input type="number" id="capacity_mah" name="capacity_mah" min="0"
|
||
value="{{ battery.capacity_mah or '' }}" placeholder="e.g. 2000">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="charge_cycles">Charge Cycles</label>
|
||
<input type="number" id="charge_cycles" name="charge_cycles" min="0"
|
||
value="{{ battery.charge_cycles or '' }}" placeholder="e.g. 50">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="tested_capacity_mah">Tested Capacity (mAh)</label>
|
||
<input type="number" id="tested_capacity_mah" name="tested_capacity_mah" min="0"
|
||
value="{{ battery.tested_capacity_mah or '' }}" placeholder="e.g. 1850">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="tested_date">Test Date</label>
|
||
<input type="date" id="tested_date" name="tested_date"
|
||
value="{{ battery.tested_date or '' }}">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="purchase_date">Purchase Date</label>
|
||
<input type="date" id="purchase_date" name="purchase_date"
|
||
value="{{ battery.purchase_date or '' }}">
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label>Storage Location</label>
|
||
<select id="storage-select" onchange="metaSelectChanged(this,'storage_location')">
|
||
<option value="">— none —</option>
|
||
{% for loc in storage_locations|default([]) %}
|
||
<option value="{{ loc }}" {% if battery.storage_location == loc %}selected{% endif %}>{{ loc }}</option>
|
||
{% endfor %}
|
||
<option value="__new__" {% if battery.storage_location and battery.storage_location not in storage_locations|default([]) %}selected{% endif %}>➕ New location…</option>
|
||
</select>
|
||
<input type="text" id="storage_location" name="storage_location"
|
||
value="{{ battery.storage_location or '' }}"
|
||
placeholder="e.g. Drawer 2, Toolbox, Shelf A"
|
||
style="display:{% if battery.storage_location and battery.storage_location not in storage_locations|default([]) %}''{% else %}none{% endif %};margin-top:0.4rem;">
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="notes">Notes</label>
|
||
<textarea id="notes" name="notes" placeholder="No notes yet…">{{ battery.notes or '' }}</textarea>
|
||
</div>
|
||
|
||
<button class="btn btn-primary" type="submit">Save Details</button>
|
||
</form>
|
||
</div>
|
||
|
||
<!-- Actions -->
|
||
<div class="card">
|
||
<h2>Actions</h2>
|
||
<div class="form-actions">
|
||
{% if battery.is_available() %}
|
||
<a class="btn btn-primary" href="{{ url_for('battery_assign', battery_id=battery.id) }}">Assign to Device</a>
|
||
{% endif %}
|
||
|
||
{% if battery.is_installed() %}
|
||
<form method="post" action="{{ url_for('battery_unassign', battery_id=battery.id) }}">
|
||
<button class="btn btn-warning" type="submit">Unassign</button>
|
||
</form>
|
||
{% endif %}
|
||
|
||
{% if not battery.is_retired() %}
|
||
<form method="post" action="{{ url_for('battery_retire', battery_id=battery.id) }}">
|
||
<button class="btn btn-secondary" type="submit">Retire Battery</button>
|
||
</form>
|
||
{% else %}
|
||
<form method="post" action="{{ url_for('battery_unretire', battery_id=battery.id) }}">
|
||
<button class="btn btn-secondary" type="submit">Unretire Battery</button>
|
||
</form>
|
||
{% endif %}
|
||
|
||
<a class="btn btn-danger" href="{{ url_for('battery_delete', battery_id=battery.id) }}">Delete Battery</a>
|
||
</div>
|
||
</div>
|
||
|
||
<a class="text-muted" href="{{ url_for('dashboard') }}">← Back to Dashboard</a>
|
||
|
||
<script>
|
||
function metaSelectChanged(sel, inputId) {
|
||
var input = document.getElementById(inputId);
|
||
if (sel.value === '__new__') {
|
||
input.style.display = '';
|
||
input.value = '';
|
||
input.focus();
|
||
} else {
|
||
input.style.display = 'none';
|
||
input.value = sel.value;
|
||
}
|
||
}
|
||
</script>
|
||
{% endblock %}
|