Files
toptrumps/templates/cards/_form.html
T
Ross c71c229ea8 .
2025-12-05 13:53:08 +00:00

194 lines
7.1 KiB
HTML

<div class="card-form card">
{% if card %}
<form method="post" enctype="multipart/form-data" action="{% url 'cards:edit' card.pk %}" hx-post="{% url 'cards:edit' card.pk %}" hx-target="#card-{{ card.pk }}" hx-swap="outerHTML">
{% else %}
<form method="post" enctype="multipart/form-data" action="{% url 'cards:create' %}" hx-post="{% url 'cards:create' %}" hx-target="#cards-list .columns" hx-swap="afterbegin">
{% endif %}
{% csrf_token %}
{{ form.non_field_errors }}
<div class="field">
<label class="label">{{ form.name.label }}</label>
<div class="control">
{{ form.name }}
</div>
</div>
<div class="field is-horizontal">
<div class="field-body">
<div class="field">
<label class="label">{{ form.era.label }}</label>
<div class="control">
<div class="select is-fullwidth">{{ form.era }}</div>
</div>
</div>
<div class="field">
<label class="label">{{ form.diet.label }}</label>
<div class="control">
<div class="select is-fullwidth">{{ form.diet }}</div>
</div>
</div>
</div>
</div>
<div class="field">
<label class="label">{{ form.description.label }}</label>
<div class="control">
{{ form.description }}
</div>
</div>
<div class="field">
<label class="label">{{ form.facts.label }}</label>
<div class="control">
{{ form.facts }}
<p class="help">One fact per line — will be shown as bullet points on the card.</p>
</div>
</div>
<div class="field">
<label class="label">{{ form.image.label }}</label>
<div class="control">
<div class="file has-name">
<label class="file-label">
{{ form.image }}
<span class="file-cta">
<span class="file-icon">📁</span>
<span class="file-label">Choose a file…</span>
</span>
<span class="file-name" style="margin-left:0.5rem">No file chosen</span>
</label>
</div>
</div>
</div>
<div class="field">
<label class="label">{{ form.background.label }}</label>
<div class="control">
<div style="display:none">{{ form.background }}</div>
<div class="background-picker">
<div class="bg-options">
<div class="bg-option" data-bg-id="" role="button" tabindex="0">Use site default</div>
{% for bg in backgrounds %}
<div class="bg-option{% if form.instance.background and form.instance.background.pk == bg.pk %} selected{% endif %}" data-bg-id="{{ bg.pk }}" title="{{ bg.title|default:'Background' }}">
<img src="{{ bg.image.url }}" alt="{{ bg.title }}">
</div>
{% endfor %}
</div>
<p class="help">Optional: choose a background image to use for this card.</p>
</div>
</div>
</div>
<script>
(function(){
const script = document.currentScript;
const root = script && script.parentElement ? script.parentElement : document;
const picker = root.querySelector('.background-picker');
if(!picker) return;
const select = root.querySelector('select[name="background"]');
const options = picker.querySelectorAll('.bg-option');
function clearSelected(){ options.forEach(o=>o.classList.remove('selected')); }
options.forEach(function(opt){
opt.addEventListener('click', function(){
const id = opt.getAttribute('data-bg-id');
clearSelected();
opt.classList.add('selected');
if(select){ select.value = id || '';
// dispatch change for any listeners
select.dispatchEvent(new Event('change', { bubbles: true }));
}
});
});
})();
</script>
<script>
(function(){
const script = document.currentScript;
const formRoot = script && script.parentElement ? script.parentElement : document;
const fileInputs = formRoot.querySelectorAll('input[type=file]');
fileInputs.forEach(function(fi){
fi.addEventListener('change', function(){
const wrapper = fi.closest('.file');
if(!wrapper) return;
const label = wrapper.querySelector('.file-name');
if(!label) return;
if(fi.files.length === 0) label.textContent = 'No file chosen';
else label.textContent = fi.files.length > 1 ? fi.files.length + ' files selected' : fi.files[0].name;
try {
const nameInput = formRoot.querySelector('input[name="name"]');
if(nameInput && (!nameInput.value || nameInput.value.trim() === '')){
const f = fi.files && fi.files[0];
if(f && f.name){
const base = f.name.replace(/\.[^/.]+$/, '');
const title = base.replace(/[_-]+/g, ' ').split(/\s+/).map(function(w){ return w.length? (w.charAt(0).toUpperCase() + w.slice(1)) : ''; }).join(' ').trim();
if(title) nameInput.value = title;
}
}
}catch(e){ /* ignore UI enhancement errors */ }
});
const outerLabel = fi.closest('.file').querySelector('.file-label');
if(outerLabel && !outerLabel.contains(fi)){
outerLabel.addEventListener('click', function(e){ fi.click(); });
}
});
})();
</script>
<div class="field is-horizontal">
<div class="field-body">
<div class="field">
<label class="label">{{ form.speed.label }}</label>
<div class="control">
<div class="field has-addons">
<div class="control is-expanded">{{ form.speed }}</div>
<div class="control">
<a class="button is-static">km/h</a>
</div>
</div>
</div>
</div>
<div class="field">
<label class="label">{{ form.weight.label }}</label>
<div class="control">
<div class="field has-addons">
<div class="control is-expanded">{{ form.weight }}</div>
<div class="control">
<a class="button is-static">kg</a>
</div>
</div>
</div>
</div>
<div class="field">
<label class="label">{{ form.intelligence.label }}</label>
<div class="control">
<div class="field has-addons">
<div class="control is-expanded">{{ form.intelligence }}</div>
<div class="control">
<a class="button is-static">score</a>
</div>
</div>
</div>
</div>
<div class="field">
<label class="label">{{ form.height.label }}</label>
<div class="control">
<div class="field has-addons">
<div class="control is-expanded">{{ form.height }}</div>
<div class="control">
<a class="button is-static">m</a>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="field is-grouped">
<div class="control">
<button class="button is-primary" type="submit">Save</button>
</div>
<div class="control">
<button class="button is-light" type="button" onclick="document.getElementById('htmx-form').innerHTML=''">Cancel</button>
</div>
</div>
</form>
</div>