Files
battery-tracker-app/templates/battery_add.html
T
iterminate 39b52a3fa4 Replace browser confirm() dialogs with custom modal; add live label preview on battery add form
- base.html: add CSS/HTML/JS for styled in-app confirmation modal (dark-mode compatible via CSS vars)
- device_list, battery_detail: convert onsubmit confirm() to declarative data-confirm attributes
- dashboard: convert bulk Delete/Install buttons to use modal helpers (submitWithAction pattern)
- app.py: pass brand_counts dict to battery_add template
- battery_add.html: show live "Will create: Brand 001 → Brand 003" preview as brand/quantity change
- tests: add two tests covering brand_counts server-side rendering
2026-04-13 09:53:21 -05:00

149 lines
5.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}Add Batteries — Battery Tracker{% endblock %}
{% block content %}
<h1>Add Batteries</h1>
<div class="card">
<form method="post" action="{{ url_for('battery_add') }}">
<div class="form-grid-2col" style="display:grid;grid-template-columns:1fr 1fr;gap:0 1rem;">
<div class="form-group" style="grid-column:1/-1;">
<label for="brand-select">Brand <span class="text-danger">*</span></label>
<select id="brand-select" onchange="metaSelectChanged(this, 'brand')">
<option value="">— select a brand —</option>
{% for b in brands|default([]) %}
<option value="{{ b }}">{{ b }}</option>
{% endfor %}
<option value="__new__"> New brand…</option>
</select>
<input type="text" id="brand" name="brand" value="{{ form_brand|default('') }}"
placeholder="Type new brand name" required
style="display:none;margin-top:0.4rem;">
</div>
<div class="form-group">
<label for="count">Quantity</label>
<input type="number" id="count" name="count" value="{{ form_count|default(1) }}" min="1" max="50">
<small class="text-muted">Labels are auto-generated (e.g. Eneloop 001, Eneloop 002)</small>
<div id="label-preview" style="font-size:0.85rem;color:var(--link);margin-top:0.3rem;font-weight:500;min-height:1.2em;"></div>
</div>
<div class="form-group">
<label for="capacity_mah">Capacity (mAh)</label>
<input type="number" id="capacity_mah" name="capacity_mah" min="0"
value="" placeholder="e.g. 2000 — optional">
</div>
<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 }}">{{ opt }}</option>
{% endfor %}
<option value="__new__">Other…</option>
</select>
<input type="text" id="size" name="size" value=""
placeholder="Enter size" style="display:none;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 }}">{{ opt }}</option>
{% endfor %}
<option value="__new__">Other…</option>
</select>
<input type="text" id="chemistry" name="chemistry" value=""
placeholder="Enter chemistry" style="display:none;margin-top:0.4rem;">
</div>
<div class="form-group">
<label for="purchase_date">Purchase Date</label>
<input type="date" id="purchase_date" name="purchase_date" value="">
</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 }}">{{ loc }}</option>
{% endfor %}
<option value="__new__"> New location…</option>
</select>
<input type="text" id="storage_location" name="storage_location" value=""
placeholder="e.g. Drawer 2, Toolbox, Shelf A"
style="display:none;margin-top:0.4rem;">
</div>
<div class="form-group">
<label for="notes">Notes</label>
<textarea id="notes" name="notes"
placeholder="Optional notes applied to all batteries…">{{ form_notes|default('') }}</textarea>
</div>
<div class="form-actions">
<button class="btn btn-primary" type="submit">Add Batteries</button>
<a class="btn btn-secondary" href="{{ url_for('dashboard') }}">Cancel</a>
</div>
</form>
</div>
<script>
var brandCounts = {{ brand_counts|default({})|tojson }};
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;
}
if (inputId === 'brand') updateLabelPreview();
}
function updateLabelPreview() {
var brand = document.getElementById('brand').value.trim();
var count = parseInt(document.getElementById('count').value, 10) || 1;
var preview = document.getElementById('label-preview');
if (!brand) { preview.textContent = ''; return; }
var existing = brandCounts[brand] !== undefined ? brandCounts[brand] : 0;
var first = existing + 1;
var last = existing + count;
var pad = function(n) { return n.toString().padStart(3, '0'); };
preview.textContent = count === 1
? 'Will create: ' + brand + ' ' + pad(first)
: 'Will create: ' + brand + ' ' + pad(first) + ' \u2192 ' + brand + ' ' + pad(last);
}
document.getElementById('count').addEventListener('input', updateLabelPreview);
document.getElementById('brand').addEventListener('input', updateLabelPreview);
// Restore brand state on error re-render
(function () {
var input = document.getElementById('brand');
var sel = document.getElementById('brand-select');
if (!input.value) return;
for (var i = 0; i < sel.options.length; i++) {
if (sel.options[i].value === input.value) {
sel.value = input.value;
input.style.display = 'none';
return;
}
}
sel.value = '__new__';
input.style.display = '';
}());
</script>
{% endblock %}