This commit is contained in:
@@ -726,36 +726,49 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
document.addEventListener('pkt:open-consent', openConsentModal);
|
||||
|
||||
const readAvatarValue = (form, field) => {
|
||||
const checked = form.querySelector(`[data-avatar-field="${field}"]:checked`);
|
||||
if (checked) return checked.value;
|
||||
const input = form.querySelector(`[data-avatar-field="${field}"]`);
|
||||
return input ? input.value : '';
|
||||
};
|
||||
|
||||
const avatarComponentFieldMap = {
|
||||
avatar_lorelei_eyes_variant: 'eyesVariant',
|
||||
avatar_lorelei_eyebrows_variant: 'eyebrowsVariant',
|
||||
avatar_lorelei_mouth_variant: 'mouthVariant',
|
||||
avatar_lorelei_glasses_variant: 'glassesVariant',
|
||||
avatar_lorelei_hair_variant: 'hairVariant',
|
||||
avatar_lorelei_beard_variant: 'beardVariant',
|
||||
avatar_lorelei_earrings_variant: 'earringsVariant',
|
||||
};
|
||||
|
||||
const avatarComponentFields = Object.keys(avatarComponentFieldMap);
|
||||
|
||||
const buildAvatarParams = (form, overrides = {}) => {
|
||||
const seed = overrides.avatar_preset || readAvatarValue(form, 'avatar_preset');
|
||||
if (!seed) return null;
|
||||
|
||||
const params = new URLSearchParams({ seed });
|
||||
avatarComponentFields.forEach((field) => {
|
||||
const value = Object.prototype.hasOwnProperty.call(overrides, field)
|
||||
? overrides[field]
|
||||
: readAvatarValue(form, field);
|
||||
const param = avatarComponentFieldMap[field];
|
||||
if (value && param) params.set(param, value);
|
||||
});
|
||||
|
||||
return params;
|
||||
};
|
||||
|
||||
const updateAvatarPreview = (form) => {
|
||||
const preview = form.querySelector('[data-avatar-preview] .pkt-avatar');
|
||||
if (!preview) return;
|
||||
|
||||
const readValue = (field) => {
|
||||
const checked = form.querySelector(`[data-avatar-field="${field}"]:checked`);
|
||||
if (checked) return checked.value;
|
||||
const input = form.querySelector(`[data-avatar-field="${field}"]`);
|
||||
return input ? input.value : '';
|
||||
};
|
||||
const image = preview.querySelector('.pkt-avatar__img');
|
||||
if (!image) return;
|
||||
|
||||
const checked = form.querySelector('[data-avatar-field="avatar_preset"]:checked');
|
||||
const seed = checked?.value || '';
|
||||
if (!seed) return;
|
||||
|
||||
const params = new URLSearchParams({ seed });
|
||||
[
|
||||
['avatar_lorelei_eyes_variant', 'eyesVariant'],
|
||||
['avatar_lorelei_eyebrows_variant', 'eyebrowsVariant'],
|
||||
['avatar_lorelei_mouth_variant', 'mouthVariant'],
|
||||
['avatar_lorelei_glasses_variant', 'glassesVariant'],
|
||||
['avatar_lorelei_hair_variant', 'hairVariant'],
|
||||
['avatar_lorelei_beard_variant', 'beardVariant'],
|
||||
['avatar_lorelei_earrings_variant', 'earringsVariant'],
|
||||
].forEach(([field, param]) => {
|
||||
const value = readValue(field);
|
||||
if (value) params.set(param, value);
|
||||
});
|
||||
const params = buildAvatarParams(form);
|
||||
if (!params) return;
|
||||
|
||||
const url = `/api/avatar?${params.toString()}`;
|
||||
if (!url) return;
|
||||
@@ -763,48 +776,50 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
};
|
||||
|
||||
const updateAvatarOptionPreviews = (form) => {
|
||||
const baseSeed = readValue('avatar_preset');
|
||||
if (!baseSeed) return;
|
||||
|
||||
const currentValues = {};
|
||||
[
|
||||
'avatar_lorelei_eyes_variant',
|
||||
'avatar_lorelei_eyebrows_variant',
|
||||
'avatar_lorelei_mouth_variant',
|
||||
'avatar_lorelei_glasses_variant',
|
||||
'avatar_lorelei_hair_variant',
|
||||
'avatar_lorelei_beard_variant',
|
||||
'avatar_lorelei_earrings_variant',
|
||||
].forEach((field) => {
|
||||
const checkedField = form.querySelector(`[data-avatar-field="${field}"]:checked`);
|
||||
currentValues[field] = checkedField ? checkedField.value : '';
|
||||
});
|
||||
|
||||
const fieldMap = {
|
||||
avatar_lorelei_eyes_variant: 'eyesVariant',
|
||||
avatar_lorelei_eyebrows_variant: 'eyebrowsVariant',
|
||||
avatar_lorelei_mouth_variant: 'mouthVariant',
|
||||
avatar_lorelei_glasses_variant: 'glassesVariant',
|
||||
avatar_lorelei_hair_variant: 'hairVariant',
|
||||
avatar_lorelei_beard_variant: 'beardVariant',
|
||||
avatar_lorelei_earrings_variant: 'earringsVariant',
|
||||
};
|
||||
|
||||
form.querySelectorAll('[data-avatar-option-thumb]').forEach((image) => {
|
||||
const field = image.getAttribute('data-avatar-option-field') || '';
|
||||
const value = image.getAttribute('data-avatar-option-value') || '';
|
||||
const params = new URLSearchParams({ seed: baseSeed });
|
||||
Object.entries(currentValues).forEach(([currentField, currentValue]) => {
|
||||
const param = fieldMap[currentField];
|
||||
if (!param) return;
|
||||
const appliedValue = currentField === field ? value : currentValue;
|
||||
if (appliedValue) params.set(param, appliedValue);
|
||||
});
|
||||
const params = buildAvatarParams(form, { [field]: value });
|
||||
if (!params) return;
|
||||
|
||||
image.src = `/api/avatar?${params.toString()}`;
|
||||
});
|
||||
};
|
||||
|
||||
const renderAvatarSeedChoices = (form, seeds) => {
|
||||
const picker = form.querySelector('[data-avatar-seed-picker]');
|
||||
const grid = form.querySelector('[data-avatar-seed-picker-grid]');
|
||||
if (!picker || !grid) return;
|
||||
|
||||
grid.innerHTML = '';
|
||||
seeds.forEach((seed, index) => {
|
||||
const params = buildAvatarParams(form, { avatar_preset: seed });
|
||||
if (!params) return;
|
||||
|
||||
const card = document.createElement('button');
|
||||
card.type = 'button';
|
||||
card.className = 'avatar-seed-card';
|
||||
card.setAttribute('data-avatar-seed-option', seed);
|
||||
card.innerHTML = `
|
||||
<span class="avatar-seed-card__thumb">
|
||||
<img src="/api/avatar?${params.toString()}" alt="Grundvariante ${index + 1}">
|
||||
</span>
|
||||
<span class="avatar-seed-card__label">Variante ${index + 1}</span>
|
||||
`;
|
||||
card.addEventListener('click', () => {
|
||||
const seedField = form.querySelector('[data-avatar-field="avatar_preset"]');
|
||||
if (!(seedField instanceof HTMLInputElement)) return;
|
||||
seedField.value = seed;
|
||||
picker.hidden = true;
|
||||
updateAvatarPreview(form);
|
||||
updateAvatarOptionPreviews(form);
|
||||
});
|
||||
grid.appendChild(card);
|
||||
});
|
||||
|
||||
picker.hidden = false;
|
||||
};
|
||||
|
||||
document.querySelectorAll('[data-avatar-builder]').forEach((form) => {
|
||||
updateAvatarPreview(form);
|
||||
updateAvatarOptionPreviews(form);
|
||||
@@ -837,15 +852,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
});
|
||||
|
||||
[
|
||||
'avatar_lorelei_eyes_variant',
|
||||
'avatar_lorelei_eyebrows_variant',
|
||||
'avatar_lorelei_mouth_variant',
|
||||
'avatar_lorelei_glasses_variant',
|
||||
'avatar_lorelei_hair_variant',
|
||||
'avatar_lorelei_beard_variant',
|
||||
'avatar_lorelei_earrings_variant',
|
||||
].forEach((field) => {
|
||||
avatarComponentFields.forEach((field) => {
|
||||
form.querySelectorAll(`[data-avatar-field="${field}"]`).forEach((input) => {
|
||||
input.addEventListener('change', () => setActiveComponentPanel(field));
|
||||
});
|
||||
@@ -866,7 +873,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
'veit', 'vito', 'yaro', 'yuri', 'zeno', 'zuri',
|
||||
];
|
||||
const slugifySeed = (value) => value.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 64) || 'papa-kind-treff';
|
||||
const dicebearUrl = (seed) => `/api/avatar?seed=${encodeURIComponent(seed)}`;
|
||||
const buildSeed = () => {
|
||||
const prefix = avatarPrefixes[Math.floor(Math.random() * avatarPrefixes.length)];
|
||||
const suffix = avatarSuffixes[Math.floor(Math.random() * avatarSuffixes.length)];
|
||||
@@ -877,9 +883,20 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
form.querySelector('[data-avatar-reroll]')?.addEventListener('click', () => {
|
||||
const seedField = form.querySelector('[data-avatar-field="avatar_preset"]');
|
||||
if (!(seedField instanceof HTMLInputElement)) return;
|
||||
seedField.value = buildSeed();
|
||||
updateAvatarPreview(form);
|
||||
updateAvatarOptionPreviews(form);
|
||||
const currentSeed = readAvatarValue(form, 'avatar_preset');
|
||||
const seeds = [];
|
||||
while (seeds.length < 8) {
|
||||
const candidate = buildSeed();
|
||||
if (candidate === currentSeed || seeds.includes(candidate)) continue;
|
||||
seeds.push(candidate);
|
||||
}
|
||||
|
||||
renderAvatarSeedChoices(form, seeds);
|
||||
});
|
||||
|
||||
form.querySelector('[data-avatar-seed-picker-close]')?.addEventListener('click', () => {
|
||||
const picker = form.querySelector('[data-avatar-seed-picker]');
|
||||
if (picker) picker.hidden = true;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user