194 lines
7.1 KiB
HTML
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>
|