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'),
|
title: isEdit ? t('birthdays.editTitle') : t('birthdays.newTitle'),
|
||||||
content: `
|
content: `
|
||||||
<div class="birthday-modal">
|
<div class="birthday-modal">
|
||||||
<div class="birthday-preview" id="birthday-preview">${birthdayPreviewHtml(birthday?.name || '', photoData)}</div>
|
<div class="birthday-modal__identity">
|
||||||
<div class="form-group">
|
<button type="button" class="birthday-avatar-editor" id="birthday-preview" aria-label="${t('birthdays.photoLabel')}">
|
||||||
<label class="form-label" for="bd-name">${t('birthdays.nameLabel')}</label>
|
${birthdayPreviewHtml(birthday?.name || '', photoData)}
|
||||||
<input class="form-input" id="bd-name" type="text" value="${esc(birthday?.name || '')}" autocomplete="name">
|
</button>
|
||||||
</div>
|
<div class="birthday-modal__fields">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="bd-birth-date">${t('birthdays.birthDateLabel')}</label>
|
<label class="form-label" for="bd-name">${t('birthdays.nameLabel')}</label>
|
||||||
<input class="form-input" id="bd-birth-date" type="date" value="${esc(birthday?.birth_date || '')}">
|
<input class="form-input" id="bd-name" type="text" value="${esc(birthday?.name || '')}" autocomplete="name">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label" for="bd-photo">${t('birthdays.photoLabel')}</label>
|
<label class="form-label" for="bd-birth-date">${t('birthdays.birthDateLabel')}</label>
|
||||||
<input class="form-input" id="bd-photo" type="file" accept="image/png,image/jpeg,image/webp,image/gif">
|
<input class="form-input" id="bd-birth-date" type="date" value="${esc(birthday?.birth_date || '')}">
|
||||||
<div class="form-help">${t('birthdays.photoOptional')}</div>
|
</div>
|
||||||
<div class="birthday-modal__photo-actions">
|
|
||||||
<button type="button" class="btn btn--secondary" id="bd-remove-photo">${t('birthdays.removePhoto')}</button>
|
|
||||||
</div>
|
</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">
|
<div class="form-group">
|
||||||
<label class="form-label" for="bd-notes">${t('birthdays.notesLabel')}</label>
|
<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>
|
<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) {
|
onSave(panel) {
|
||||||
const nameInput = panel.querySelector('#bd-name');
|
const nameInput = panel.querySelector('#bd-name');
|
||||||
const preview = panel.querySelector('#birthday-preview');
|
const preview = panel.querySelector('#birthday-preview');
|
||||||
|
const fileInput = panel.querySelector('#bd-photo');
|
||||||
|
const photoEdit = panel.querySelector('#bd-photo-edit');
|
||||||
const renderPreview = () => {
|
const renderPreview = () => {
|
||||||
preview.replaceChildren();
|
preview.innerHTML = birthdayPreviewHtml(nameInput.value.trim(), photoData);
|
||||||
preview.insertAdjacentHTML('beforeend', birthdayPreviewHtml(nameInput.value.trim(), photoData));
|
|
||||||
};
|
};
|
||||||
nameInput.addEventListener('input', renderPreview);
|
nameInput.addEventListener('input', renderPreview);
|
||||||
panel.querySelectorAll('.js-date-input').forEach((input) => {
|
preview.addEventListener('click', () => fileInput?.click());
|
||||||
input.addEventListener('blur', () => {
|
photoEdit?.addEventListener('click', () => fileInput?.click());
|
||||||
const parsed = parseDateInput(input.value);
|
fileInput?.addEventListener('change', async (e) => {
|
||||||
if (parsed) input.value = formatDateInput(parsed);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
panel.querySelector('#bd-photo').addEventListener('change', async (e) => {
|
|
||||||
const file = e.target.files?.[0];
|
const file = e.target.files?.[0];
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
try {
|
try {
|
||||||
@@ -333,7 +337,7 @@ function openBirthdayModal({ mode, birthday = null }) {
|
|||||||
});
|
});
|
||||||
panel.querySelector('#bd-remove-photo').addEventListener('click', () => {
|
panel.querySelector('#bd-remove-photo').addEventListener('click', () => {
|
||||||
photoData = null;
|
photoData = null;
|
||||||
panel.querySelector('#bd-photo').value = '';
|
if (fileInput) fileInput.value = '';
|
||||||
renderPreview();
|
renderPreview();
|
||||||
});
|
});
|
||||||
panel.querySelector('#bd-cancel').addEventListener('click', closeModal);
|
panel.querySelector('#bd-cancel').addEventListener('click', closeModal);
|
||||||
|
|||||||
@@ -287,6 +287,21 @@
|
|||||||
background: color-mix(in srgb, var(--module-accent) 16%, white);
|
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 {
|
.birthday-preview__image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -300,7 +315,43 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.birthday-modal__photo-actions {
|
.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 {
|
.birthday-modal__hint {
|
||||||
@@ -308,6 +359,16 @@
|
|||||||
font-size: var(--text-sm);
|
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) {
|
@media (max-width: 960px) {
|
||||||
.birthdays-grid {
|
.birthdays-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
|||||||
Reference in New Issue
Block a user