feat: standardize admin form limits and guidance

This commit is contained in:
Tống Thành Đạt
2026-04-10 15:55:15 +07:00
parent 7ce5921fe0
commit 51c6303437
34 changed files with 1692 additions and 361 deletions

View File

@@ -75,7 +75,7 @@
<i class="fas fa-upload me-1"></i>Upload
</button>
</div>
<small class="text-muted d-block mt-1">The contact hero currently renders at about 1496x544px on desktop. Recommended minimum upload: 1920x700px.</small>
<small class="text-muted d-block mt-1">Recommended minimum upload: 1920x700px.</small>
</div>
<div class="col-md-7">
<div id="heroImagePreview" style="height: 300px;">
@@ -181,7 +181,6 @@
name="cardTitle_<%= index %>"
value="<%= card.title || '' %>"
maxlength="40" data-maxlength="40">
<small class="text-muted d-block mt-1">Recommended maximum: 40 characters.</small>
</div>
<div class="col-md-12">
<label class="form-label">Icon Type</label>
@@ -1210,63 +1209,12 @@
});
}
function ensureContactCounter(input) {
if (!input || !input.dataset.maxlength) {
return null;
}
if (!input.id) {
input.id = `contactField_${Math.random().toString(36).slice(2, 10)}`;
}
const field = input.closest('.col-md-12, .col-md-7, .col-md-6, .col-md-5, .col-md-4, .col-md-3, .col-md-2, .col-12') || input.parentElement;
const anchor = input.closest('.input-group') || input;
const parent = anchor?.parentElement || field;
if (!field || !anchor || !parent) {
return null;
}
let hint = field.querySelector(`[data-counter-for="${input.id}"]`);
if (!hint) {
hint = document.createElement('small');
hint.className = 'form-text contact-limit-counter text-secondary';
hint.dataset.counterFor = input.id;
}
if (hint.previousElementSibling !== anchor) {
parent.insertBefore(hint, anchor.nextSibling);
}
return hint;
}
function updateContactCounter(input) {
const hint = ensureContactCounter(input);
if (!hint) {
return;
}
const max = Number(input.dataset.maxlength);
if (Number.isFinite(max) && max > 0 && (input.value || '').length > max) {
input.value = (input.value || '').slice(0, max);
}
const length = (input.value || '').length;
hint.textContent = `${length}/${max} characters`;
hint.classList.toggle('text-danger', length >= max);
}
function initContactCharacterCounters(scope = document) {
scope.querySelectorAll('input[data-maxlength], textarea[data-maxlength]').forEach((input) => {
updateContactCounter(input);
scope.querySelectorAll('.contact-limit-counter').forEach((node) => node.remove());
if (input.dataset.counterBound === 'true') {
return;
}
input.dataset.counterBound = 'true';
input.addEventListener('input', () => updateContactCounter(input));
});
if (window.AdminFormHelpers) {
window.AdminFormHelpers.refresh(scope);
}
}
function updateAllJsonInputs(data) {
@@ -1327,7 +1275,6 @@
<div class="col-md-6">
<label class="form-label">Title</label>
<input type="text" class="form-control" name="cardTitle_${index}" maxlength="40" data-maxlength="40">
<small class="text-muted d-block mt-1">Recommended maximum: 40 characters.</small>
</div>
<div class="col-md-12">
<label class="form-label">Icon Type</label>