fix(birthdays): match profile picture editor pattern
This commit is contained in:
+29
-25
@@ -275,23 +275,30 @@ function openBirthdayModal({ mode, birthday = null }) {
|
||||
title: isEdit ? t('birthdays.editTitle') : t('birthdays.newTitle'),
|
||||
content: `
|
||||
<div class="birthday-modal">
|
||||
<div class="birthday-preview" id="birthday-preview">${birthdayPreviewHtml(birthday?.name || '', photoData)}</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="bd-name">${t('birthdays.nameLabel')}</label>
|
||||
<input class="form-input" id="bd-name" type="text" value="${esc(birthday?.name || '')}" autocomplete="name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="bd-birth-date">${t('birthdays.birthDateLabel')}</label>
|
||||
<input class="form-input" id="bd-birth-date" type="date" value="${esc(birthday?.birth_date || '')}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="bd-photo">${t('birthdays.photoLabel')}</label>
|
||||
<input class="form-input" id="bd-photo" type="file" accept="image/png,image/jpeg,image/webp,image/gif">
|
||||
<div class="form-help">${t('birthdays.photoOptional')}</div>
|
||||
<div class="birthday-modal__photo-actions">
|
||||
<button type="button" class="btn btn--secondary" id="bd-remove-photo">${t('birthdays.removePhoto')}</button>
|
||||
<div class="birthday-modal__identity">
|
||||
<button type="button" class="birthday-avatar-editor" id="birthday-preview" aria-label="${t('birthdays.photoLabel')}">
|
||||
${birthdayPreviewHtml(birthday?.name || '', photoData)}
|
||||
</button>
|
||||
<div class="birthday-modal__fields">
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="bd-name">${t('birthdays.nameLabel')}</label>
|
||||
<input class="form-input" id="bd-name" type="text" value="${esc(birthday?.name || '')}" autocomplete="name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="bd-birth-date">${t('birthdays.birthDateLabel')}</label>
|
||||
<input class="form-input" id="bd-birth-date" type="date" value="${esc(birthday?.birth_date || '')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input class="sr-only" id="bd-photo" type="file" accept="image/png,image/jpeg,image/webp,image/gif">
|
||||
<div class="birthday-modal__photo-actions">
|
||||
<button type="button" class="birthday-modal__photo-action" id="bd-photo-edit" aria-label="${t('birthdays.photoLabel')}" title="${t('birthdays.photoLabel')}">
|
||||
<i data-lucide="pencil" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button type="button" class="birthday-modal__photo-action birthday-modal__photo-action--danger" id="bd-remove-photo" aria-label="${t('birthdays.removePhoto')}" title="${t('birthdays.removePhoto')}">
|
||||
<i data-lucide="trash-2" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="bd-notes">${t('birthdays.notesLabel')}</label>
|
||||
<textarea class="form-input" id="bd-notes" rows="3" placeholder="${t('birthdays.notesPlaceholder')}">${esc(birthday?.notes || '')}</textarea>
|
||||
@@ -310,18 +317,15 @@ function openBirthdayModal({ mode, birthday = null }) {
|
||||
onSave(panel) {
|
||||
const nameInput = panel.querySelector('#bd-name');
|
||||
const preview = panel.querySelector('#birthday-preview');
|
||||
const fileInput = panel.querySelector('#bd-photo');
|
||||
const photoEdit = panel.querySelector('#bd-photo-edit');
|
||||
const renderPreview = () => {
|
||||
preview.replaceChildren();
|
||||
preview.insertAdjacentHTML('beforeend', birthdayPreviewHtml(nameInput.value.trim(), photoData));
|
||||
preview.innerHTML = birthdayPreviewHtml(nameInput.value.trim(), photoData);
|
||||
};
|
||||
nameInput.addEventListener('input', renderPreview);
|
||||
panel.querySelectorAll('.js-date-input').forEach((input) => {
|
||||
input.addEventListener('blur', () => {
|
||||
const parsed = parseDateInput(input.value);
|
||||
if (parsed) input.value = formatDateInput(parsed);
|
||||
});
|
||||
});
|
||||
panel.querySelector('#bd-photo').addEventListener('change', async (e) => {
|
||||
preview.addEventListener('click', () => fileInput?.click());
|
||||
photoEdit?.addEventListener('click', () => fileInput?.click());
|
||||
fileInput?.addEventListener('change', async (e) => {
|
||||
const file = e.target.files?.[0];
|
||||
if (!file) return;
|
||||
try {
|
||||
@@ -333,7 +337,7 @@ function openBirthdayModal({ mode, birthday = null }) {
|
||||
});
|
||||
panel.querySelector('#bd-remove-photo').addEventListener('click', () => {
|
||||
photoData = null;
|
||||
panel.querySelector('#bd-photo').value = '';
|
||||
if (fileInput) fileInput.value = '';
|
||||
renderPreview();
|
||||
});
|
||||
panel.querySelector('#bd-cancel').addEventListener('click', closeModal);
|
||||
|
||||
@@ -287,6 +287,21 @@
|
||||
background: color-mix(in srgb, var(--module-accent) 16%, white);
|
||||
}
|
||||
|
||||
.birthday-avatar-editor {
|
||||
width: 84px;
|
||||
height: 84px;
|
||||
margin: 0 auto var(--space-3);
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: var(--radius-full);
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: color-mix(in srgb, var(--module-accent) 16%, white);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.birthday-preview__image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -300,7 +315,43 @@
|
||||
}
|
||||
|
||||
.birthday-modal__photo-actions {
|
||||
margin-top: var(--space-2);
|
||||
display: flex;
|
||||
gap: var(--space-2);
|
||||
justify-content: center;
|
||||
margin-top: calc(var(--space-1) * -1);
|
||||
margin-bottom: var(--space-2);
|
||||
}
|
||||
|
||||
.birthday-modal__photo-action {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: var(--radius-full);
|
||||
border: 1px solid var(--color-border);
|
||||
background: var(--color-surface);
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
.birthday-modal__photo-action svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.birthday-modal__photo-action--danger {
|
||||
color: var(--color-danger);
|
||||
}
|
||||
|
||||
.birthday-modal__identity {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: var(--space-4);
|
||||
}
|
||||
|
||||
.birthday-modal__fields {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.birthday-modal__hint {
|
||||
@@ -308,6 +359,16 @@
|
||||
font-size: var(--text-sm);
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.birthday-modal__identity {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.birthday-modal__photo-actions {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.birthdays-grid {
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
Reference in New Issue
Block a user