Files
idle_clicker/public/js/ui/achievementsView.js
T

58 lines
2.0 KiB
JavaScript

// Achievements tab: milestones with a small permanent bonus each.
import { statValue } from '../engine/achievements.js';
import { t } from '../services/i18n.js';
import { h, icon } from './dom.js';
import { effectText, setText } from './text.js';
export function createAchievementsView(root) {
let ctx;
let fmt;
let summary;
const rows = new Map();
function rebuild(newCtx, formatter) {
ctx = newCtx;
fmt = formatter;
rows.clear();
summary = h('p', { class: 'hint' });
const list = h('ul', { class: 'cards cards--grid' });
for (const a of ctx.achievements) {
const progress = h('p', { class: 'card__meta' });
const li = h(
'li',
{ class: 'card' },
icon(`ach.${a.id}`),
h(
'div',
{ class: 'card__body' },
h('h3', { class: 'card__title', text: t(`ach.title.${a.id}`) }),
h('p', { class: 'card__desc', text: t(`ach.cond.${a.condition.stat}`, { value: fmt.number(a.condition.min) }) }),
h('p', { class: 'card__meta', text: effectText(a.effect, fmt) }),
progress,
),
);
list.append(li);
rows.set(a.id, { a, li, progress });
}
root.replaceChildren(
h('section', { class: 'panel panel--wide' }, h('h2', { class: 'panel__title', text: t('tab.achievements') }), summary, list),
);
}
function update(state) {
const bonus = state.achievements.reduce((product, id) => product * ctx.achievementsById.get(id).effect.value, 1);
setText(summary, t('ach.summary', { done: state.achievements.length, total: ctx.achievements.length, bonus: fmt.number(bonus) }));
for (const { a, li, progress } of rows.values()) {
const done = state.achievements.includes(a.id);
li.classList.toggle('card--done', done);
li.classList.toggle('card--locked', !done);
const value = Math.min(statValue(state, a.condition.stat), a.condition.min);
setText(progress, done ? t('ach.done') : `${fmt.number(Math.floor(value))} / ${fmt.number(a.condition.min)}`);
}
}
return { rebuild, update };
}