Fixed RPG
This commit is contained in:
@@ -14,3 +14,94 @@ export async function copyToClipboard(text) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const GENRE_LABELS = {
|
||||
adventure: 'Приключение',
|
||||
horror: 'Хоррор',
|
||||
romance: 'Романтика',
|
||||
slice_of_life: 'Повседневность',
|
||||
fantasy: 'Фэнтези',
|
||||
sci_fi: 'Sci-Fi',
|
||||
};
|
||||
|
||||
export function initWizard(modalEl, { totalSteps, onStepChange, validateStep }) {
|
||||
let step = 1;
|
||||
const pages = modalEl.querySelectorAll('.wizard-page');
|
||||
const dots = modalEl.querySelectorAll('.wizard-step-dot');
|
||||
const prevBtn = modalEl.querySelector('[id$="Prev"]');
|
||||
const nextBtn = modalEl.querySelector('[id$="Next"]');
|
||||
const saveBtn = modalEl.querySelector('[id$="Save"], [id$="Confirm"], [id$="Create"]');
|
||||
|
||||
function render() {
|
||||
pages.forEach(p => p.classList.toggle('active', Number(p.dataset.step) === step));
|
||||
dots.forEach(d => {
|
||||
const n = Number(d.dataset.step);
|
||||
d.classList.toggle('active', n === step);
|
||||
d.classList.toggle('done', n < step);
|
||||
});
|
||||
prevBtn?.classList.toggle('hidden', step <= 1);
|
||||
nextBtn?.classList.toggle('hidden', step >= totalSteps);
|
||||
saveBtn?.classList.toggle('hidden', step < totalSteps);
|
||||
onStepChange?.(step);
|
||||
}
|
||||
|
||||
function goTo(next) {
|
||||
if (next > step && validateStep && !validateStep(step)) return;
|
||||
step = Math.max(1, Math.min(totalSteps, next));
|
||||
render();
|
||||
}
|
||||
|
||||
prevBtn?.addEventListener('click', () => goTo(step - 1));
|
||||
nextBtn?.addEventListener('click', () => goTo(step + 1));
|
||||
|
||||
render();
|
||||
|
||||
return {
|
||||
reset() { step = 1; render(); },
|
||||
getStep: () => step,
|
||||
goTo,
|
||||
render,
|
||||
};
|
||||
}
|
||||
|
||||
export function bindGenreGrid(gridEl, selectedSet, onChange) {
|
||||
gridEl.addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('.genre-btn');
|
||||
if (!btn) return;
|
||||
const genre = btn.dataset.genre;
|
||||
if (selectedSet.has(genre)) {
|
||||
selectedSet.delete(genre);
|
||||
btn.classList.remove('selected');
|
||||
} else {
|
||||
selectedSet.add(genre);
|
||||
btn.classList.add('selected');
|
||||
}
|
||||
onChange?.();
|
||||
});
|
||||
}
|
||||
|
||||
export function resetGenreGrid(gridEl, selectedSet) {
|
||||
selectedSet.clear();
|
||||
gridEl.querySelectorAll('.genre-btn').forEach(b => b.classList.remove('selected'));
|
||||
}
|
||||
|
||||
export function getRpgSettingsFromDom(prefix = '') {
|
||||
const id = (name) => document.getElementById(prefix + name);
|
||||
return {
|
||||
dice: id('settingDice')?.checked ?? true,
|
||||
narrator: id('settingNarrator')?.checked ?? true,
|
||||
quests: id('settingQuests')?.checked ?? true,
|
||||
affinity: id('settingAffinity')?.checked ?? true,
|
||||
choices: id('settingChoices')?.checked ?? true,
|
||||
};
|
||||
}
|
||||
|
||||
export function formatSessionDate(iso) {
|
||||
if (!iso) return '';
|
||||
const d = new Date(iso.includes('T') ? iso : iso.replace(' ', 'T') + 'Z');
|
||||
if (Number.isNaN(d.getTime())) return '';
|
||||
const now = new Date();
|
||||
const sameDay = d.toDateString() === now.toDateString();
|
||||
if (sameDay) return d.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' });
|
||||
return d.toLocaleDateString('ru-RU', { day: 'numeric', month: 'short' });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user